Scripts/Managers/GameManager.cs
using System;
using Milaine.TreeSkills;

namespace Milaine.Managers;

public sealed class GameManager : Component {
  [Property, Title("IdleManager")]
  [Feature("General")]
  public IdleManager IdleManagerInstance { get; set; }

  [Property, Title("InvestmentManager")]
  [Feature("General")]
  public InvestmentManager InvestmentManagerInstance { get; set; }

  [Property, Title("SkillTreeBootstrap")]
  [Feature("General")]
  public SkillTreeBootstrap SkillTreeBootstrapInstance { get; set; }

  [Property, Title("DayNightManager")]
  [Feature("General")]
  public DayNightManager DayNightManagerInstance { get; set; }

  public Action OnLooseGame { get; set; }
  public Action OnWinGame { get; set; }

  private List<SkillNodeData> skillsUsed = [];
  private int maxSkillPoints = 0;
  private int skillPoints = 0;
  private bool isPlaying = true;
  private bool isGameWin = false;

  public bool IsGameWin {
    get => isGameWin;
  }

  protected override void OnAwake() {
    TreeSkillState.Instance.OnUnlocked += OnUnlocked;
    TreeSkillState.Instance.SpendPoint += OnSpendPoint;
    TreeSkillState.Instance.GetSkillPoints = GetSkillPoints;
    DayNightManagerInstance.OnEndDay += OnEndDay;
    InvestmentManagerInstance.OnChange += OnInvestmentManagerChange;
  }

  protected override void OnDestroy() {
    TreeSkillState.Instance.OnUnlocked -= OnUnlocked;
    TreeSkillState.Instance.SpendPoint -= OnSpendPoint;
    DayNightManagerInstance.OnEndDay -= OnEndDay;
    InvestmentManagerInstance.OnChange -= OnInvestmentManagerChange;
  }

  private void OnEndDay() {
    if (DayNightManagerInstance.Day < 5) {
      return;
    }

    isPlaying = false;
    isGameWin = false;
    OnLooseGame?.Invoke();
  }

  private void OnInvestmentManagerChange(Portfolio portfolio) {
    if (!isPlaying) {
      return;
    }

    int total = (int)portfolio.investment;
    int goal = IdleManagerInstance.Goal;

    if (total >= goal) {
      isPlaying = false;
      isGameWin = true;
      DayNightManagerInstance.ResetManager();
      OnWinGame?.Invoke();
    }
  }

  private void OnUnlocked(SkillNodeData node) {
    if (skillsUsed.Contains(node)) {
      return;
    }

    skillsUsed.Add(node);

    switch (node.Category) {
      case SkillCategory.Dollars:
        IdleManagerInstance.ImprovePoint(node.Point);
        break;
      case SkillCategory.DollarAutomatic:
        IdleManagerInstance.ImprovePasiveDollar(node.Point);
        break;
      case SkillCategory.Wallet:
        InvestmentManagerInstance.ImproveWallet(node.Point);
        break;
      case SkillCategory.Investment:
        InvestmentManagerInstance.ImprovePerformance(node.Point);
        break;
      case SkillCategory.Dividends:
        InvestmentManagerInstance.ImproveDividends(node.Point);
        break;
      case SkillCategory.WalletPlus:
        InvestmentManagerInstance.ImproveDeposit(node.Point);
        break;
    }
  }

  private int GetSkillPoints() => skillPoints;

  private void OnSpendPoint() {
    skillPoints--;
  }

  public void Restart() {
    DayNightManagerInstance.Restart();
    TreeSkillState.Instance.Restart();
    skillsUsed = [];
    maxSkillPoints += 1;
    skillPoints += maxSkillPoints;

    IdleManagerInstance.Restart();
    InvestmentManagerInstance.Restart();
  }
}