package src.fr.impl;

import src.fr.api.Category;
import src.fr.api.PartType;
import src.fr.api.CompatibilityManager;
import src.fr.api.Configuration;
import src.fr.api.Part;

import java.util.HashSet;
import java.util.Optional;
import java.util.Set;

public class ConfigurationImpl implements Configuration {
    private Set<Part> selectedParts = new HashSet<Part> ();
    private CompatibilityManager compatibilityManager;
    private static int NB_CATEGORY = 4;
    
    public ConfigurationImpl(CompatibilityManager cm){
        this.compatibilityManager=cm;
    }

    @Override
    public boolean isValid() {
        boolean test = true;
        for(Part pt1: selectedParts){
            boolean test_Requirement = true;
            boolean test_Incompabilities = true;
            System.out.println("name : " + pt1.getType().getName());
            //Verifier Requirements
            for(PartType require : compatibilityManager.getRequirements(pt1.getType())){
                test_Requirement = false;
                System.out.println("\tRequirement : " + require.getName());
                //if(!selectedParts.contains(require)) return false;
                //IN V2, instead of verify if it's in selectedParts,
                //we will compare its type and selectedParts 
                //boolean no_error = true;
                for(Part pt2 : selectedParts){
                    System.out.println("\t\tname : " + pt2.getType().getName());
                    if (pt2.getType().equals(require)){
                        test_Requirement = true;
                        //no_error= true; 
                        break;
                    }
                }   
            }
            if(test_Requirement) System.out.println("\tok");
            else System.out.println("\tnot ok");
            //Verifier Incompabilities
            for(PartType incompa : compatibilityManager.getIncompatibilities(pt1.getType())){
                System.out.println("\tIncompatibility : " + incompa.getName());
                for (Part selectPart : selectedParts){
                    if(selectPart.getType().equals(incompa)){
                        test_Incompabilities = false;
                        break;
                    }
                }
            }
            if(test_Incompabilities) System.out.println("\tok");
            else System.out.println("\tnot ok");
            System.out.println(test_Requirement + " " + test_Incompabilities);
            test = test && test_Requirement && test_Incompabilities;
        }
        return test;
    }

    public int getTotalPrice(){
        int prix_final=0;
        if(this.isValid()){
            for(Part pt: selectedParts){
                prix_final+=((PartImpl)pt).getPrice();
            }
            return prix_final;
        }else{
            return -1;
        }
    }
    
    @Override
    public boolean isComplete() {
        if(selectedParts.size()==NB_CATEGORY){
            return true;
        }
        return false;
    }

    @Override
    public Set<Part> getSelectedParts() {
        return selectedParts;
    }

    @Override
    public void selectPart(PartType chosenPart) {
        Category category_chosenPart = chosenPart.getCategory();
        //Vérifier s'il y a des pièces dans la même catégorie, si oui return
        for(Part pt: selectedParts){
            if(pt.getCategory().equals(category_chosenPart)){    
                System.out.println("Il y a une pièce dans la même catégorie dans la configuration");
                selectedParts.remove(pt);
                break;
            }
        }
        PartImpl newPart = ((PartTypeImpl)chosenPart).newInstance();
        newPart.setType(chosenPart);
        selectedParts.add(newPart);
        //System.out.println(chosenPart.getName() + " : size = " + selectedParts.size());
    }

    @Override
    public Optional<Part> getSelectionForCategory(Category category) {
        for( Part pt: selectedParts){
            if(pt.getCategory().equals(category)){
                return Optional.of(pt);
            }
        }
        return Optional.empty();
    }

    @Override
    public void unselectPartType(Category categoryToClear) {
        for( Part pt: selectedParts){
            if(pt.getCategory().equals(categoryToClear)){
                selectedParts.remove(pt);
            }
        }
        System.out.println("Il n'y a pas des pièces dans cette catégorie");

    }

    @Override
    public void clear() {
        this.selectedParts.clear();;
    }

    public Part getPart(Category part){
        Part engine = null;
        for( Part pt: selectedParts){
            if(pt.getCategory() == part){
                engine = pt;
                break;
            }
        }
        return engine;
    }
}
