using GatherAndDefend.Events;
using GatherAndDefend.LevelEditor;
using System;
using UnityEngine;

/// <summary>
/// Sert d'inventaire et gère l'accès aux ressources
/// </summary>
public class ResourceManager : Singleton<ResourceManager>
{
    private int _rockAmount = 0;
    private int _woodAmount = 0;
    private int _foodAmount = 0;

    private float _currentPopulation;
    private float _maximumPopulation;

    private const int MAX = int.MaxValue;
    private const int MIN = 0;

    public ResourceManager()
    {
        EventAggregator.Instance.GetEvent<LevelLoadedEvent>().Attach(InitializeResources);
        EventAggregator.Instance.GetEvent<ExitingLevelEvent>().Attach(ResetResources);
    }

    private void ResetResources()
    {
        _rockAmount = 0;
        _woodAmount = 0;
        _foodAmount = 0;
        _currentPopulation = 0;
        _maximumPopulation = 0;
    }
    private void InitializeResources(Level level)
    {
        RockAmount = level.StartRock;
        WoodAmount = level.StartWood;
        FoodAmount = level.StartFood;
        CurrentPopulation = 0;
        MaximumPopulation = level.StartPopulation;
    }

    public int RockAmount
    {
        set
        {
            if (value != _rockAmount)
            {
                _rockAmount = Mathf.Clamp(value, MIN, MAX);
                EventAggregator.Instance.GetEvent<ResourcesChangedEvent>().Invoke();
            }
        }
        get { return _rockAmount; }
    }
    public int WoodAmount
    {
        set
        {
            if (value != _woodAmount)
            {
                _woodAmount = Mathf.Clamp(value, MIN, MAX);
                EventAggregator.Instance.GetEvent<ResourcesChangedEvent>().Invoke();
            }
        }
        get { return _woodAmount; }
    }
    public int FoodAmount
    {
        set
        {
            if (value != _foodAmount)
            {
                _foodAmount = value;
                EventAggregator.Instance.GetEvent<ResourcesChangedEvent>().Invoke();
            }
        }
        get { return _foodAmount; }
    }

    public float CurrentPopulation
    {
        get => _currentPopulation;
        set
        {
            if (_currentPopulation != value)
            {
                _currentPopulation = value;
                EventAggregator.Instance.GetEvent<PopulationChangedEvent>().Invoke(
                    new PopulationChangedEventArgs() { 
                        Pop = _currentPopulation,
                        MaxPop = MaximumPopulation
                    });
            }
        }
    }
    public float MaximumPopulation
    {
        get => _maximumPopulation;
        set
        {
            if (_maximumPopulation != value)
            {
                _maximumPopulation = value;
                EventAggregator.Instance.GetEvent<PopulationChangedEvent>().Invoke(
                    new PopulationChangedEventArgs()
                    {
                        Pop = CurrentPopulation,
                        MaxPop = _maximumPopulation
                    });
            }
        }
    }

    public void Remove(int rock, int wood, int food)
    {
        int oldRock = _rockAmount, oldWood = _woodAmount, oldFood = _foodAmount;
        _rockAmount = (_rockAmount - rock) < MIN ? MIN : _rockAmount - rock;
        _woodAmount = (_woodAmount - wood) < MIN ? MIN : _woodAmount - wood;
        _foodAmount = (_foodAmount - food) < MIN ? MIN : _foodAmount - food;

        if (oldRock != _rockAmount || oldFood != _foodAmount || oldWood != _woodAmount)
        {
            EventAggregator.Instance.GetEvent<ResourcesChangedEvent>().Invoke();
        }
    }

    public bool EnoughFor(int rock, int wood, int food = 0)
    {
        return _rockAmount >= rock
            && _woodAmount >= wood
            && _foodAmount >= food;
    }
    public bool EnoughPopulationFor(int population = 1) 
    {
        return _currentPopulation + population <= _maximumPopulation;
    }
}
