package dev.fyloz.trial.colorrecipesexplorer.utils;

import dev.fyloz.trial.colorrecipesexplorer.model.*;
import dev.fyloz.trial.colorrecipesexplorer.model.dto.MixFormDto;
import dev.fyloz.trial.colorrecipesexplorer.service.model.MaterialJavaService;
import dev.fyloz.trial.colorrecipesexplorer.service.model.MixTypeService;
import dev.fyloz.trial.colorrecipesexplorer.model.Material;

import java.util.*;

public class MixBuilder {

    private MixTypeService mixTypeService;
    private MaterialJavaService materialService;

    private Long id;
    private Recipe recipe;
    private MixType mixType;
    private String location;
    private List<MixQuantity> mixQuantities = new ArrayList<>();

    private Map<String, Float> quantities = new LinkedHashMap<>();

    public MixBuilder(MixTypeService mixTypeService, MaterialJavaService materialService) {
        this.mixTypeService = mixTypeService;
        this.materialService = materialService;
    }

    public MixBuilder withMix(Mix mix) {
        this.id = mix.getId();
        this.recipe = mix.getRecipe();
        this.mixType = mix.getMixType();
        this.location = mix.getLocation();
        this.mixQuantities = mix.getMixQuantities();

        return this;
    }

    public MixBuilder withDto(MixFormDto dto) {
        String mixTypeName = dto.getMixTypeName();

        if (this.mixType == null) {
            this.mixType = mixTypeService.create(mixTypeName, dto.getMaterialType());
        } else {
            this.mixType = new MixType(this.mixType.getId(), this.mixType.getName(), this.mixType.getMaterial());

            if (materialService.existsByName(mixTypeName)) {
                this.mixType.setName(mixTypeName, false);
                this.mixType.setMaterial(materialService.getByName(mixTypeName));
            } else {
                this.mixType.setName(mixTypeName, true);
            }

            this.mixType.getMaterial().setMaterialType(dto.getMaterialType());
        }

        this.recipe = dto.getRecipe();

        for (int i = 0; i < dto.getMaterials().size(); i++)
            quantities.put(dto.getMaterials().get(i), dto.getQuantities().get(i));

        return this;
    }

    public MixBuilder withId(Long id) {
        this.id = id;

        return this;
    }

    public MixBuilder withRecipe(Recipe recipe) {
        this.recipe = recipe;

        return this;
    }

    public MixBuilder withMixType(MixType mixType) {
        this.mixType = mixType;

        return this;
    }

    public MixBuilder withMixQuantity(MixQuantity mixQuantity) {
        this.mixQuantities.add(mixQuantity);

        return this;
    }

    public MixBuilder withMixQuantities(List<MixQuantity> mixQuantities) {
        this.mixQuantities = mixQuantities;

        return this;
    }

    public Mix build() {
        Mix mix = new Mix(this.recipe, this.mixType);

        createMixQuantities(mix);

        mix.setId(this.id);
        mix.setLocation(this.location);
        mix.setMixQuantities(this.mixQuantities);

        return mix;
    }

    private void createMixQuantities(Mix mix) {
        List<MixQuantity> mixQuantities = new ArrayList<>();

        for (Map.Entry<String, Float> quantityEntry : quantities.entrySet()) {
            Material material = materialService.getByName(quantityEntry.getKey());
            Float quantity = quantityEntry.getValue();

            mixQuantities.add(new MixQuantity(mix, material, quantity));
        }

        this.mixQuantities = mixQuantities;
    }
}
