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

[System.Serializable]
public class FlowerColors
{
    public Color color;
    public int qtty;
}

[System.Serializable]
public class FlowerNeeds
{
    public float alimentNeed;
    public float alimentHave;
    public FlowerColors[] myColors;



    public bool CanLevelUp()
    {
        if (alimentHave >= alimentNeed) { return true; }
        else { return false; }
    }

    public static bool CompareColors(Color colorA, Color colorB)
    {
        if (Mathf.Abs(colorA.r - colorB.r) > 0.1f) return false;
        if (Mathf.Abs(colorA.g - colorB.g) > 0.1f) return false;
        if (Mathf.Abs(colorA.b - colorB.b) > 0.1f) return false;
        return true;
    }
}

public class PlantsController : Nodo
{
    public enum PlantName
    {
        SunFlower,
        Tulip,
        Cactus
    }

    public Color myColorHodeiEsteSi;
    public PlantName plantName;

    public Sprite seed;
    public Sprite[] sunFlower;
    public Sprite[] tulip;
    public Sprite[] cactus;

    SpriteRenderer spriteRenderer;
    //public Color myColor;

    public FlowerNeeds FirstLevelNeeds;
    public FlowerNeeds SecondLevelNeeds; //alimentsNeed = alimentsHave * 2
    public FlowerNeeds ThirdLevelNeeds; //alimentsNeed = alimentsHave * 1.5
    public FlowerNeeds ActualNeeds;
    public FlowerColors[] ConnectedToMe;
    public bool needsSatisfied;
    public Action OnColorChange;
    public int m_Lvl = 0;
    LevelController m_LevelController;
    public bool thisPlantWin = false;
    public float LifeLoss = 1;

    public sliderControl slider;

    public int extaRootLv2 = 5;
    public int extaRootLv3 = 10;

    public ParticleSystem PlantLevelUpgrade_particles;
    public ParticleSystem PlantWin_particles;

    public static Action OnDie;

    void Awake()
    {
        m_LevelController = GameObject.FindGameObjectWithTag("LevelController").GetComponent<LevelController>();
        entriesType = new GridTypes[4];
        ActualNeeds = FirstLevelNeeds;
        m_PlantsController = this;
    }

    private void Start()
    {
        InitNeeds();
        spriteRenderer = GetComponent<SpriteRenderer>();
        InitColors();
        SetValue();
        SetPlantSprite();
    }

    private void InitNeeds()
    {
        SecondLevelNeeds.alimentHave = SecondLevelNeeds.alimentNeed / 2;
        ThirdLevelNeeds.alimentHave = ThirdLevelNeeds.alimentNeed / 1.5f;
    }

    private void SetPlantSprite()
    {
        if (m_Lvl != 0)
        {
            switch (plantName)
            {
                case PlantName.Cactus:
                    spriteRenderer.sprite = cactus[m_Lvl - 1];
                    break;
                case PlantName.Tulip:
                    spriteRenderer.sprite = tulip[m_Lvl - 1];
                    break;
                case PlantName.SunFlower:
                    spriteRenderer.sprite = sunFlower[m_Lvl - 1];
                    break;
            }
        }
        else
        {
            spriteRenderer.sprite = seed;
        }
    }

    void InitColors()
    {
        FlowerColors[] newArray = new FlowerColors[ActualNeeds.myColors.Length];

        for (int i = 0; i < ActualNeeds.myColors.Length; i++)
        {
            newArray[i] = new FlowerColors();
            newArray[i].color = ActualNeeds.myColors[i].color;
            newArray[i].qtty = 0;

            if (ActualNeeds != FirstLevelNeeds)
            {
                foreach (FlowerColors fn in ConnectedToMe)
                {
                    if (FlowerNeeds.CompareColors(fn.color, newArray[i].color)) newArray[i].qtty = fn.qtty;
                }
            }
        }
        ConnectedToMe = newArray;
    }
    private void OnMouseDown()
    {
        Manager.Instance.SetPlantMode(this);
    }

    void Update()
    {
        if (Manager.Instance.StillPlaying())
        {
            if (m_Lvl == 0 && Manager.Instance.GetCanStartGeneringAliments()) 
            {
                m_Lvl = 1; SetPlantSprite();
                SetValue();
            }

            if (!needsSatisfied && m_Lvl > 0)
            {
                ActualNeeds.alimentHave -= LifeLoss * Time.deltaTime;
                SetValue();
                if (ActualNeeds.alimentHave <= 0) OnDie?.Invoke();
            }
        }
    }

    bool IAcceptSupply(Color color)
    {
        if (needsSatisfied) return true;

        foreach (FlowerColors fn in ActualNeeds.myColors)
        {
            if (FlowerNeeds.CompareColors(fn.color, color)) return true;
        }
        return false;
    }

    public bool IAcceptMoreSupply(Color color)
    {
        if (!IAcceptSupply(color)) return false;

        foreach (FlowerColors fc in ConnectedToMe)
        {
            foreach (FlowerColors fn in ActualNeeds.myColors)
            {
                if (FlowerNeeds.CompareColors(fc.color, color) && FlowerNeeds.CompareColors(fn.color, color))
                {
                    if (fc.qtty < fn.qtty)
                    {
                        return true;
                    }
                    else return false;
                }
            }
        }
        return false;
    }

    internal void SupplyReached(Color color)
    {
        float r = 0;
        float g = 0;
        float b = 0;
        int accum = 0;

        foreach (FlowerColors fn in ConnectedToMe)
        {
            if (FlowerNeeds.CompareColors(fn.color, color)) fn.qtty++;
            r += fn.color.r * fn.qtty;
            g += fn.color.g * fn.qtty;
            b += fn.color.b * fn.qtty;
            accum += fn.qtty;
        }

        needsSatisfied = CheckIfSatisfied();
    }

    private bool CheckIfSatisfied()
    {
        foreach (FlowerColors fn in ActualNeeds.myColors)
        {
            if (IAcceptMoreSupply(fn.color)) return false;
        }
        return true;
    }

    private void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.tag == ("Nutrient"))
        {
            CheckNutrient(collision.gameObject.GetComponent<AlimentController>().GetColor());
            Destroy(collision.gameObject);
        }
    }

    private void CheckNutrient(Color _colorNut)
    {
        if (needsSatisfied)
        {
            if (ActualNeeds.alimentHave < ActualNeeds.alimentNeed)
            {
                ActualNeeds.alimentHave += 1;
                SetValue();

                if (ActualNeeds.alimentHave >= ActualNeeds.alimentNeed)
                {
                    if (m_Lvl < 3)
                        LevelUp();
                    else
                    {
                        m_Lvl = 4;
                        SetPlantSprite();
                        thisPlantWin = true;
                        PlantLevelUpgrade_particles.Play();
                        PlantWin_particles.Play();
                        Manager.Instance.SetWin();
                    }
                }
            }
        }
    }

    private void LevelUp()
    {
        
        
        m_Lvl++;
        SetPlantSprite();
        switch (m_Lvl)
        {
            case 2:
                m_LevelController.maxRoot += extaRootLv2;
                ActualNeeds = SecondLevelNeeds;
                InitColors();
                break;
            case 3:
                m_LevelController.maxRoot += extaRootLv3;
                ActualNeeds = ThirdLevelNeeds;
                InitColors();
                break;
        }

        //Level up effects
        FMODUnity.RuntimeManager.PlayOneShot("event:/Plant/Plant_levelUpgrade");
        PlantLevelUpgrade_particles.Play();

        needsSatisfied = CheckIfSatisfied();
    }


    internal void RemovedSupply(Color colorThisSupply)
    {
        foreach (FlowerColors fn in ConnectedToMe)
        {
            if (FlowerNeeds.CompareColors(fn.color, colorThisSupply))
            {
                fn.qtty--;
                needsSatisfied = CheckIfSatisfied();
                thisPlantWin = false;
                return;
            }
        }
    }

    public void SetValue()
    {
        if (!slider.gameObject.activeInHierarchy) slider.gameObject.SetActive(true);
        slider.SetSliderValue(ActualNeeds.alimentHave / ActualNeeds.alimentNeed, m_Lvl);
    }
}