using System.Collections;
using TMPro;
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine;

public class Upgrade
{
    public string name = "MT";
    public int amount = 0;

    public Upgrade(string n)
    {
        name = n;
    }
}
public class Upgrades
{
    public Upgrade mopUpgrade = new Upgrade("Mop Radius");
    public Upgrade speedUpgrade = new Upgrade("Move speed");
    public Upgrade ropeUpgrade = new Upgrade("Longer Rope");
    public Upgrade healthUpgrade = new Upgrade("More health");
    public Upgrade damageUpgrade = new Upgrade("More rope damage");
    public Upgrade bloodUpgrade = new Upgrade("MORE BLOOD!");
    public Upgrade reelUpgrade = new Upgrade("Faster rope reel speed");
    public Upgrade reviveUpgrade = new Upgrade("Adds an extra revive");
}

public class Upgrader : MonoBehaviour
{
    public GameObject player1;
    public GameObject player2;

    public BloodComputeShader bloodManager;
    public RopeSimulator rope;

    public Upgrades upgrades { get; private set; }

    public float mopSizeIncrease = 1.1f;
    public float speedIncrease = 1.1f;
    public float ropeIncrease = 1.1f;
    public float healthIncrease = 1.1f;
    public float damageIncrease = 1.1f;
    public float bloodIncrease = 1.1f;
    public float reelIncrease = 1.1f;

    public int upgradeCost = 7000;

    private RectTransform Player1Cursor;
    private RectTransform Player2Cursor;

    private PlayerInput Player1Input;
    private PlayerInput Player2Input;

    private float acceptTime = 0f;

    private Image background;

    private Image[] upgradeImages = new Image[8];

    private bool prevCouldUpgrade = true;

    public Image BloodMeter;
    public TMPro.TextMeshProUGUI description;

    // Start is called before the first frame update
    void Start()
    {
        Player1Cursor = transform.Find("Player1 Cursor").GetComponent<RectTransform>();
        Player2Cursor = transform.Find("Player2 Cursor").GetComponent<RectTransform>();

        Player1Input = player1.GetComponent<PlayerInput>();
        Player2Input = player2.GetComponent<PlayerInput>();

        background = GetComponent<Image>();

        int idx = 0;

        foreach (Image i in GetComponentsInChildren<Image>())
        {
            if (i.gameObject.name.StartsWith("Upgrade"))
                upgradeImages[idx++] = i;
        }

        upgrades = new Upgrades();

        StartCoroutine(updateBloodMeter());
    }

    bool canUpgrade()
    {
        return bloodManager.score >= upgradeCost;
        // return true;
    }

    int getRegion(float x, float y, int regions)
    {
        if (x + y == 0)
            return -1;

        float angle = Mathf.Atan2(x, -y) + Mathf.PI;
        float regionSize = (Mathf.PI * 2.0f) / ((float)regions);
        int region = (int)((((Mathf.PI * 2.0f) - angle) / regionSize) + 0.5f);

        if (region > regions - 1)
            return 0;

        return region;
    }

    // Update is called once per frame
    void Update()
    {
        bool upgrade = canUpgrade();

        if (canUpgrade())
        {

            if (!prevCouldUpgrade)
            {
                background.color = Color.white;
                foreach (Image i in upgradeImages)
                {
                    i.color = Color.white;
                }

                Player1Cursor.gameObject.SetActive(true);
                Player2Cursor.gameObject.SetActive(true);
            }

            int p1a = getRegion(Player1Input.look.x, Player1Input.look.y, 8);
            int p2a = getRegion(Player2Input.look.x, Player2Input.look.y, 8);

            if (p1a != -1 && p2a == p1a)
            {
                if (acceptTime > 2f)
                {
                    switch (p1a)
                    {
                        case 0:
                            UpgradeMopSize();
                            break;
                        case 1:
                            UpgradeSpeed();
                            break;
                        case 2:
                            RopeUpgrade();
                            break;
                        case 3:
                            HealthUpgrade();
                            break;
                        case 4:
                            DamageUpgrade();
                            break;
                        case 5:
                            BloodUpgrade();
                            break;
                        case 6:
                            ReelUpgrade();
                            break;
                        case 7:
                            ReviveUpgrade();
                            break;
                    }

                    // Subtract blood
                    bloodManager.score -= upgradeCost;
                    acceptTime = 0f;
                }
                else
                {
                    acceptTime += Time.deltaTime;

                    foreach (Image i in upgradeImages)
                    {
                        i.fillAmount = 1f;
                        i.gameObject.transform.localScale = Vector3.one;
                    }

                    switch (p1a)
                    {
                        case 0:
                            description.text = upgrades.mopUpgrade.name;
                            break;
                        case 1:
                            description.text = upgrades.speedUpgrade.name;
                            break;
                        case 2:
                            description.text = upgrades.ropeUpgrade.name;
                            break;
                        case 3:
                            description.text = upgrades.healthUpgrade.name;
                            break;
                        case 4:
                            description.text = upgrades.damageUpgrade.name;
                            break;
                        case 5:
                            description.text = upgrades.bloodUpgrade.name;
                            break;
                        case 6:
                            description.text = upgrades.reelUpgrade.name;
                            break;
                        case 7:
                            description.text = upgrades.reviveUpgrade.name;
                            break;
                    }

                    upgradeImages[p1a].fillAmount = acceptTime / 2f;
                    upgradeImages[p1a].transform.localScale = Vector3.one * 2f;
                }
            }
            else
            {
                description.text = "";

                if (acceptTime > 0f)
                {
                    foreach (Image i in upgradeImages)
                    {
                        i.fillAmount = 1f;
                        i.gameObject.transform.localScale = Vector3.one;
                    }
                }

                acceptTime = 0f;
                // background.fillAmount = 0f;
            }
        }
        else if (prevCouldUpgrade)
        {
            AudioManager.PlaySound("Blood_Splatter_Large_SFX", Vector3.zero, false, false);

            description.text = "";
            background.color = Color.gray;
            foreach (Image i in upgradeImages)
            {
                i.color = Color.gray;
                i.gameObject.transform.localScale = Vector3.one;
            }

            Player1Cursor.gameObject.SetActive(false);
            Player2Cursor.gameObject.SetActive(false);
        }

        Player1Cursor.localPosition = Player1Input.look.normalized * (125 - 12);
        Player2Cursor.localPosition = Player2Input.look.normalized * (125 - 12);

        prevCouldUpgrade = upgrade;
    }

    /// Increases mop radius by 10%
    public void UpgradeMopSize()
    {
        description.text = upgrades.mopUpgrade.name;
        bloodManager.CleanRadius *= mopSizeIncrease;
        upgrades.mopUpgrade.amount++;
    }

    /// Increases move speed by 10%
    public void UpgradeSpeed()
    {
        description.text = upgrades.speedUpgrade.name;
        player1.GetComponent<PlayerMovement>().moveSpeed *= speedIncrease;
        player2.GetComponent<PlayerMovement>().moveSpeed *= speedIncrease;
        upgrades.speedUpgrade.amount++;
    }

    public void RopeUpgrade()
    {
        // todo: public methods
        description.text = upgrades.ropeUpgrade.name;
        rope.ropeMaxLength *= ropeIncrease;
        upgrades.ropeUpgrade.amount++;
    }

    public void HealthUpgrade()
    {
        description.text = upgrades.healthUpgrade.name;

        var comp1 = player1.GetComponent<HealthComponent>();
        comp1.setMaxHealth((int)(comp1.getMaxHealth() * healthIncrease));

        var comp2 = player2.GetComponent<HealthComponent>();
        comp2.setMaxHealth((int)(comp2.getMaxHealth() * healthIncrease));
        upgrades.healthUpgrade.amount++;
    }

    public void DamageUpgrade()
    {
        description.text = upgrades.damageUpgrade.name;
        // todo: public rope methods
        // rope.da
        upgrades.damageUpgrade.amount++;
    }

    public void BloodUpgrade()
    {
        description.text = upgrades.bloodUpgrade.name;
        bloodManager.scoreMult *= bloodIncrease;
        upgrades.bloodUpgrade.amount++;
    }

    public void ReelUpgrade()
    {
        // todo rope methods
        description.text = upgrades.reelUpgrade.name;
        rope.ropeExtendSpeed *= reelIncrease;
        upgrades.reelUpgrade.amount++;
    }

    public void ReviveUpgrade()
    {
        description.text = upgrades.reviveUpgrade.name;
        GameManager.Instance.AddRevive();
    }

    IEnumerator updateBloodMeter()
    {
        while (true)
        {
            yield return new WaitForSeconds(0.5f);

            BloodMeter.fillAmount = ((float)bloodManager.score) / ((float)upgradeCost);
        }

        // dont care
        yield return null;
    }

}