Newer
Older
TheVengeance-Project-IADE-Unity2D / Assets / Scripts / Buildings / UpgradeManager.cs
using Mono.Cecil;
using MyCollections.Managers;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.SqlTypes;
using System.Reflection;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

public class UpgradeManager : MonoBehaviour
{
    public UpgradeData[] upgrades;
    public GameObject[] upgradesSections;
    public GameObject[] upgradePanels;
    public Image[] upgradeButtonsImage;
    [SerializeField] private GameObject uiMainCharacter;
    private PlayerController playerController;
    private GameManager gameManager;
    private GameStateManager gameStateManager;
    private GameObject currentUpgradePanelInstance;
    private Animator animator;

    [SerializeField] private float timerPressing = 0f;
    [SerializeField] private float maxTimerPressing = 2f;
    [SerializeField] private bool isHolding = false;
    private int currentButtonIndex;

    [SerializeField] private TextMeshProUGUI playerGoldObj;

    public event Action<int> OnTakeGold;
    public event Action OnCancelUpgrade;

    private void Awake()
    {
        animator = uiMainCharacter.GetComponent<Animator>();
    }

    // Start is called before the first frame update
    void Start()
    {
        gameManager = GameManager.Instance;
        gameStateManager = GameStateManager.Instance;
        gameStateManager.PauseGame();

        OnTakeGold += SetNewAmount;
        playerGoldObj.text = gameManager.PlayerGold.ToString();

        playerController = PlayerController.Instance;
        for (int i = 0; i < upgradesSections.Length; i++)
        {
            upgradesSections[i].SetActive(true);
        }
    }

    // Update is called once per frame
    void Update()
    {
        if (isHolding)
        {
            HandleHold();
        }
    }

    private void ResetFillAmount()
    {
        Image img = upgradeButtonsImage[currentButtonIndex];

        // Start a coroutine to smoothly reset the fill amount
        StartCoroutine(SmoothResetFill(img));
    }

    private void FillUpgradeButton(Image image)
    {
        float newAmount = Mathf.Clamp(timerPressing, 0f, maxTimerPressing);
        float result = newAmount / maxTimerPressing;
        image.fillAmount = result;
    }

    public void HoldButton(int index)
    {
        Debug.Log("HoldButton Called");
        isHolding = true;
        ResetUpgradeTimer();
        currentButtonIndex = index;
    }

    public void ReleaseButton()
    {
        Debug.Log("ReleaseButton Called");
        isHolding = false;

        if (upgrades[currentButtonIndex].isUnlocked)
            return;

        if (timerPressing < maxTimerPressing)
        {
            OnCancelUpgrade?.Invoke();
            ResetFillAmount();
        }
    }

    public void ActivatePanel(int index)
    {
        upgradePanels[index].SetActive(true);
        uiMainCharacter.SetActive(false);

        for (int i = 0; i < upgradesSections.Length; i++)
        {
            upgradesSections[i].SetActive(false);
        }
    }

    private UpgradeData GetUpgrade(int index) => upgrades[index];

    //Display Upgrade Info
    public void OnDisplay(int index)
    {
        UpgradeData upgrade = GetUpgrade(index);
        currentUpgradePanelInstance = upgrade.Display(gameObject);
    }

    public void OnDisplayExit()
    {
        if (currentUpgradePanelInstance != null)
        {
            Destroy(currentUpgradePanelInstance);
        }
    }

    public void OnAttackTrigger() => animator.SetTrigger("Attack");


    //Goes Back to the previous section
    public void GoBack()
    {
        uiMainCharacter.SetActive(true);
        for (int i = 0; i < upgradesSections.Length; i++)
        {
            upgradesSections[i].SetActive(true);
        }

        for (int i = 0; i < upgradePanels.Length; i++)
        {
            upgradePanels[i].SetActive(false);
        }
    }

    //Closes the shop
    public void CloseShop()
    {
        gameStateManager.ResumeGame();
        Destroy(gameObject);
    }

    //Checks if the current Upgrade is upgradable
    public bool CanUpgrade(int index)
    {
        bool c1, c2, c3;
        if (index == 0)
        {
            c1 = gameManager.PlayerLevel >= upgrades[index].requiredLevel;
            c2 = gameManager.PlayerGold >= upgrades[index].goldAmount;
            c3 = !upgrades[index].isUnlocked;
            Debug.Log($"CAN UPGRADE RESULT: {c1}, {c2}, {c3}");
            return c1 && c2 && c3;
        }

        UpgradeData previousUpgrade = upgrades[index - 1];

        c1 = gameManager.PlayerLevel >= upgrades[index].requiredLevel;
        c2 = gameManager.PlayerGold >= upgrades[index].goldAmount;
        c3 = !upgrades[index].isUnlocked;
        Debug.Log($"CAN UPGRADE RESULT: {c1}, {c2}, {c3}");

        return previousUpgrade.isUnlocked && c1 && c2 && c3;
    }

    //Resets the upgrade button timer
    public void ResetUpgradeTimer()
    {
        Debug.Log("Resetting Timer");
        timerPressing = 0f;
    }

    public void Upgrade(int index)
    {
        if (CanUpgrade(index)) // Only upgrade if conditions are met
        {
            // Deduct the required Gold Amount
            OnTakeGold?.Invoke(upgrades[index].goldAmount);

            // Unlock the upgrade
            upgrades[index].isUnlocked = true;

            // Apply the upgrade effect (attack, defense, etc.)
            ApplyUpgradeEffect(upgrades[index]);

            // Optionally, disable the upgrade button once it's unlocked
            upgradeButtonsImage[index].fillAmount = 1f; // Set the progress bar to full
            upgradeButtonsImage[index].GetComponent<Button>().interactable = false; // Disable button interaction
        }
        else
        {
            Debug.Log("Not enough Level or Gold to upgrade.");
        }
    }

    // Handling the button hold
    private void HandleHold()
    {
        if (CanUpgrade(currentButtonIndex)) // Check if the upgrade can be performed
        {
            if (timerPressing <= maxTimerPressing)
            {
                FillUpgradeButton(upgradeButtonsImage[currentButtonIndex]);
                timerPressing += Time.unscaledDeltaTime;
            }
            else
            {
                // If the timer reaches the maximum value, complete the upgrade
                Upgrade(currentButtonIndex);
                ResetUpgradeTimer(); // Reset the timer after upgrading
                isHolding = false; // Stop holding after the upgrade is done
            }
        }
        else
        {
            // Stop holding if upgrade cannot be performed
            isHolding = false;
        }
    }

    // Coroutine to smoothly reset the fill amount
    private IEnumerator SmoothResetFill(Image image)
    {
        float duration = 0.5f;
        float elapsed = 0f;
        float initialFill = image.fillAmount;

        while (elapsed < duration)
        {
            elapsed += Time.unscaledDeltaTime;
            image.fillAmount = Mathf.Lerp(initialFill, 0f, elapsed / duration);
            yield return null;
        }

        image.fillAmount = 0f;
    }


    //Sets new amount of gold, when the player buys an Updgrade
    private void SetNewAmount(int amount)
    {
        int targetAmount = gameManager.PlayerGold - amount;
        int currentAmount = gameManager.PlayerGold;
        gameManager.PlayerGold = currentAmount;

        StartCoroutine(SmoothGoldTransition(targetAmount, currentAmount));
    }

    //Smoothly interpolates the new amount of gold
    private IEnumerator SmoothGoldTransition(int targetAmount, int currentAmount)
    {
        currentAmount = int.Parse(playerGoldObj.text);

        // Smooth transition over time
        float duration = 1f; // Duration for the transition
        float elapsed = 0f;

        while (elapsed < duration)
        {
            elapsed += Time.unscaledDeltaTime;
            int result = (int)Mathf.Lerp(currentAmount, targetAmount, elapsed / duration);
            playerGoldObj.text = result.ToString();
            yield return null;
        }

        // Ensure the final value is set
        playerGoldObj.text = targetAmount.ToString();
    }

    //Apply the upgrades
    private void ApplyUpgradeEffect(UpgradeData upgrade)
    {
        switch(upgrade.upgradeType)
        {
            case UpgradeType.Attack:
                playerController.CurrentPlayerAttack += upgrade.attackBonus;
                Debug.Log($"Player Attack was Upgraded to {playerController.CurrentPlayerAttack}");
                break;

            case UpgradeType.Defense:
                Debug.Log("Player Defense was Upgraded");
                break;
        }
    }
}