using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EvolutionManager : MonoBehaviour
{
    public GameObject homePrefab;
    private List<GameObject> generation;
    private int populationCount = 9;

    private float deltaX = 6f;
    private float deltaY = 3.2f;

    private List<GameObject> selection;

    public static EvolutionManager instance;

    private Vector3 positionBackUp;
    private Vector3 scaleBackUp;
    private GameObject currentFocus;
    
    // Start is called before the first frame update
    void Start()
    {
        instance = this;

        FurnitureRestrictions.SetUp();
        
        generation = new List<GameObject>();
        selection = new List<GameObject>();
        
        for (int i = 0; i < populationCount; i++)
        {
            var homeObject = Instantiate(
                homePrefab,
                new Vector3(
                    (i % 3) * deltaX - deltaX,
                    (i / 3) * deltaY - deltaY,
                    0
                ),
                Quaternion.identity,
                transform
            );

            generation.Add(homeObject);

            var home = new Home();
            home.SetUp();
            homeObject.GetComponent<HomeView>().HomeSetUp(home);
            
            var scale = Mathf.Min(4f / home.width, 2.55f / home.heigth);
            homeObject.transform.localScale = new Vector3(scale, scale, 1f);
        }
    }

    public void GenerateChildren()
    {
        var children = new List<Home>();
        var firstHome = selection[0].GetComponent<HomeView>().home;
        var secondHome = selection[1].GetComponent<HomeView>().home;
        
        // Add first selection
        children.Add(firstHome);
        
        // Add Crossover children
        children.Add(CrossOverController.CrossOver(firstHome, secondHome));
        children.Add(CrossOverController.CrossOver(firstHome, secondHome));
        children.Add(CrossOverController.CrossOver(firstHome, secondHome));
        
        // Mutate first selection
        children.Add(MutationController.Mutate(firstHome));
        children.Add(MutationController.Mutate(firstHome));
        children.Add(MutationController.Mutate(firstHome));
        
        // Mutate second selection
        children.Add(MutationController.Mutate(secondHome));
        children.Add(MutationController.Mutate(secondHome));

        // Kill last generation
        foreach (var homeObject in generation)
        {
            Destroy(homeObject);
        }
        generation = new List<GameObject>();
        
        // Recreate homes
        Utils.Shuffle(children);
        for (int i = 0; i < children.Count; i++)
        {
            var homeObject = Instantiate(
                homePrefab,
                new Vector3(
                    (i % 3) * deltaX - deltaX,
                    (i / 3) * deltaY - deltaY,
                    0
                ),
                Quaternion.identity,
                transform
            );

            generation.Add(homeObject);

            var home = children[i];
            homeObject.GetComponent<HomeView>().HomeSetUp(home);
            
            var scale = Mathf.Min(4f / home.width, 2.55f / home.heigth);
            homeObject.transform.localScale = new Vector3(scale, scale, 1f);
        }
        
        selection.Clear();
    }

    public void ToggleHomeSelection(HomeView homeView)
    {
        if (homeView.IsSelected())
        {
            homeView.RemoveSelection();
            selection.Remove(homeView.gameObject);
        }
        else
            selection.Add(homeView.gameObject);

        for (int i = 0; i < selection.Count; i++)
        {
            selection[i].GetComponent<HomeView>().SetSelected(i);
        }

        if (selection.Count >= 2)
            InputController.inputMode = InputController.InputMode.Confirmation;
    }

    public void ResetSelection()
    {
        foreach (var homeView in selection)
            homeView.GetComponent<HomeView>().RemoveSelection();
        
        selection.Clear();
    }

    public void FocusHome(GameObject homeObject)
    {
        currentFocus = homeObject;
        
        positionBackUp = currentFocus.transform.position;
        currentFocus.transform.position = Vector3.zero;
        
        scaleBackUp = currentFocus.transform.localScale;
        currentFocus.transform.localScale = new Vector3(0.7f, 0.7f, 1);

        foreach (var otherHomeObject in generation)
        {
            if (otherHomeObject != currentFocus)
                otherHomeObject.SetActive(false);
        }
        
        currentFocus.transform.Find("Selection").gameObject.SetActive(false);
    }

    public void ResetFocus()
    {
        currentFocus.transform.position = positionBackUp;
        currentFocus.transform.localScale = scaleBackUp;
        currentFocus.transform.Find("Selection").gameObject.SetActive(true);
        currentFocus = null;
        
        foreach (var otherHomeObject in generation)
            otherHomeObject.SetActive(true);
    }
}
