package dev.fyloz.trial.colorrecipesexplorer.web.controller.thymeleaf.editors;

import dev.fyloz.trial.colorrecipesexplorer.exception.model.EntityAlreadyExistsException;
import dev.fyloz.trial.colorrecipesexplorer.exception.model.EntityNotFoundException;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ModelResponseBuilder;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseCode;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseDataType;
import dev.fyloz.trial.colorrecipesexplorer.model.Mix;
import dev.fyloz.trial.colorrecipesexplorer.model.MixType;
import dev.fyloz.trial.colorrecipesexplorer.model.dto.MixFormDto;
import dev.fyloz.trial.colorrecipesexplorer.service.model.MaterialJavaService;
import dev.fyloz.trial.colorrecipesexplorer.service.model.MaterialTypeJavaService;
import dev.fyloz.trial.colorrecipesexplorer.service.model.MixService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.validation.Valid;

import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.*;

@Controller
@Profile("thymeleaf")
public class MixEditorController {

    private MixService mixService;
    private MaterialJavaService materialService;
    private MaterialTypeJavaService materialTypeService;

    @Autowired
    public MixEditorController(MixService mixService, MaterialJavaService materialService, MaterialTypeJavaService materialTypeService) {
        this.mixService = mixService;
        this.materialService = materialService;
        this.materialTypeService = materialTypeService;
    }

    @GetMapping(EDITOR_MIX_SPECIFIC)
    public ModelAndView getPage(ModelAndView model, @PathVariable Long id) {
        ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder(model).withView(EDITOR_MIX);

        try {
            Mix mix = mixService.getById(id);

            return modelResponseBuilder
                    .addResponseData(ResponseDataType.MIX, mix)
                    .addResponseData(ResponseDataType.MATERIAL_TYPE, mix.getMixType().getMaterial().getMaterialType())
                    .addResponseData(ResponseDataType.MATERIAL_TYPES, materialTypeService.getAll())
                    .addResponseData(ResponseDataType.MIX_JSON, mixService.asJson(mix))
                    .addResponseData(ResponseDataType.MATERIALS_JSON, materialService.asJson(mixService.getAvailableMaterialsForMix(mix)))
                    .build();

        } catch (EntityNotFoundException ex) {
            return modelResponseBuilder
                    .withRedirect(EDITOR_RECIPE)
                    .build();
        }
    }

    @PostMapping(value = EDITOR_MIX, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
    public ModelAndView updateMix(@ModelAttribute @Valid MixFormDto formDto, @RequestParam("mixId") Long id) {
        ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder().withRedirect(EDITOR_RECIPE_SPECIFIC, formDto.getRecipe().getId());

        try {
            Mix mix = mixService.getById(id);

            mixService.update(mix, formDto);

            return modelResponseBuilder.build();
        } catch (EntityNotFoundException ex) {
            modelResponseBuilder.addResponseCode(ResponseCode.MIX_NOT_FOUND, id).build();
        } catch (EntityAlreadyExistsException ex) {
            if (ex.getIdentifierName().equals(MixType.IDENTIFIER_MATERIAL_NAME))
                modelResponseBuilder.addResponseCode(ResponseCode.MATERIAL_AND_MIX_TYPE_CANNOT_HAVE_SAME_NAME);
            else if (ex.getIdentifierName().equals(Mix.IDENTIFIER_MIX_TYPE_NAME))
                modelResponseBuilder.addResponseCode(ResponseCode.MIX_TYPE_ALREADY_USED, ex.getRequestedId());
            else throw new EntityAlreadyExistsException(ex);
        }

        return getPage(modelResponseBuilder.build(), id);
    }
}
