using System.Collections.Generic;
using UnityEngine;

public enum GAME_EVENT
{
	/// <summary>
	/// A mission has been completed. (Parameter is the mission info as a Mission object)
	/// </summary>
    MissionCompleted,
	/// <summary>
	/// An agent has changed their away status. (Parameter is the Agent object)
	/// </summary>
	AgentAwayStatusChanged,
	/// <summary>
	/// Called whenever the amount of agents changes. (No Parameter)
	/// </summary>
	AgentCountChanged,
	/// <summary>
	/// The game progression level has changed. (No Paramter)
	/// </summary>
	ProgressionLevelChanged,
	/// <summary>
	/// The amount of influence points has changed. (Parameter is an int value for the amount of influence points)
	/// </summary>
	InfluencePointsChanged,
	/// <summary>
	/// Called when the mission details have been deselected for a mission (Parameter is the mission that was deselected)
	/// </summary>
	MissionDeselected,
}

/// <summary>
/// A global event manager that other scripts can publish events to and receive events from.
/// </summary>
public class GameEvents : BaseBehaviour
{

    #region Fields
    private Dictionary<GAME_EVENT, List<IGameEventReceiver>> gameEventTable;
    #endregion

    #region Unity Methods
    private void Awake()
    {
        InitialiseReceiverTable();
    }
    #endregion

    #region Public API
    public bool Subscribe(GAME_EVENT gameEvent, IGameEventReceiver receiver)
    {
        InitialiseReceiverTable();

        var receiverList = gameEventTable[gameEvent];
        if (receiverList.Contains(receiver))
            return false;

        receiverList.Add(receiver);
        return true;
    }

    public bool UnSubscribe(GAME_EVENT gameEvent, IGameEventReceiver receiver)
    {
        InitialiseReceiverTable();

        var receiverList = gameEventTable[gameEvent];
        return receiverList.Remove(receiver);
    }

    public bool UnSubscribeAll(IGameEventReceiver receiver)
    {
        InitialiseReceiverTable();

        bool removedFromGameEvent = false;
        foreach(var gameEvent in gameEventTable.Keys)
        {
            if (UnSubscribe(gameEvent, receiver))
                removedFromGameEvent = true;
        }
        return removedFromGameEvent;
    }

    public void Publish(GAME_EVENT gameEvent, object args=null)
    {
        InitialiseReceiverTable();

        foreach(var reciever in gameEventTable[gameEvent])
        {
            reciever.OnGameEvent(gameEvent, args);
        }
    }
    #endregion

    #region Private Methods
    private void InitialiseReceiverTable()
    {
        if(gameEventTable != null)
            return;
        gameEventTable = new Dictionary<GAME_EVENT, List<IGameEventReceiver>>();

        var allGameEvents = System.Enum.GetValues(typeof(GAME_EVENT)) as GAME_EVENT[];

        foreach(var gameEvent in allGameEvents)
            gameEventTable.Add(gameEvent, new List<IGameEventReceiver>());
    }
    #endregion

}