using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

public class EventManager
{

    private static object syncRoot;
    static EventManager()
    {
        syncRoot = new object();
    }
    private EventManager() { }
    private static EventManager instance;
    public static EventManager Instance {
        get {
            if (instance == null)
            {
                lock (syncRoot)
                {
                    if (instance == null)
                    {
                        instance = new EventManager();
                        instance.Init();
                    }
                }
            }
            return instance;
        }
    }

    private void Init()
    {

    }

    /// <summary>
    /// Triggered by when an object is destroyed
    /// </summary>
    public delegate void ObjectDestroyedHandler(LevelObjectBase obj);
    private ObjectDestroyedHandler objectDestroyedAction;
    public static void SubscribeObjectDestroyed(ObjectDestroyedHandler handler)
    {
        Instance.objectDestroyedAction += handler;
    }
    public static void UnsubscribeObjectDestroyed(ObjectDestroyedHandler handler)
    {
        Instance.objectDestroyedAction -= handler;
    }
    public static void TriggerObjectDestroyed(LevelObjectBase obj)
    {
        if (Instance.objectDestroyedAction != null)
        {
            Instance.objectDestroyedAction(obj);
        }
    }

    /// <summary>
    /// Triggered by Mob dying
    /// </summary>
    public delegate void MobDeathHandler(float xPosition, LevelObjectFaction faction);
    private MobDeathHandler mobDeathAction;
    public static void SubscribeMobDeath(MobDeathHandler handler)
    {
        Instance.mobDeathAction += handler;
    }
    public static void UnsubscribeMobDeath(MobDeathHandler handler)
    {
        Instance.mobDeathAction -= handler;
    }
    public static void TriggerMobDeath(float xPosition, LevelObjectFaction faction)
    {
        if (Instance.mobDeathAction != null)
        {
            Instance.mobDeathAction(xPosition, faction);
        }
    }

    /// <summary>
    /// Triggered by Mob requesting to play random sound
    /// </summary>
    public delegate void MobRandomSoundRequestHandler(MobBase mob);
    private MobRandomSoundRequestHandler mobRandomSoundRequestAction;
    public static void SubscribeMobRandomSoundRequest(MobRandomSoundRequestHandler handler)
    {
        Instance.mobRandomSoundRequestAction += handler;
    }
    public static void UnsubscribeMobRandomSoundRequest(MobRandomSoundRequestHandler handler)
    {
        Instance.mobRandomSoundRequestAction -= handler;
    }
    public static void TriggerMobRandomSoundRequest(MobBase mob)
    {
        if (Instance.mobRandomSoundRequestAction != null)
        {
            Instance.mobRandomSoundRequestAction(mob);
        }
    }

    /// <summary>
    /// Triggered by Random Sound Completing
    /// </summary>
    public delegate void MobRandomSoundCompleteHandler();
    private MobRandomSoundCompleteHandler mobRandomSoundCompleteAction;
    public static void SubscribeMobRandomSoundComplete(MobRandomSoundCompleteHandler handler)
    {
        Instance.mobRandomSoundCompleteAction += handler;
    }
    public static void UnsubscribeMobRandomSoundComplete(MobRandomSoundCompleteHandler handler)
    {
        Instance.mobRandomSoundCompleteAction -= handler;
    }
    public static void TriggerMobRandomSoundComplete()
    {
        if (Instance.mobRandomSoundCompleteAction != null)
        {
            Instance.mobRandomSoundCompleteAction();
        }
    }

    /// <summary>
    /// Triggered by zombie seeking an enemy
    /// </summary>
    /// <param name="zombie">The zombie seeking an enemy.</param>
    public delegate void SeekEnemyHandler(FighterZombie zombie);
    private SeekEnemyHandler seekEnemyAction;
    public static void SubscribeSeekEnemy(SeekEnemyHandler handler)
    {
        Instance.seekEnemyAction += handler;
    }
    public static void UnsubscribeSeekEnemy(SeekEnemyHandler handler)
    {
        Instance.seekEnemyAction -= handler;
    }
    public static void TriggerSeekEnemy(FighterZombie zombie)
    {
        if (Instance.seekEnemyAction != null)
        {
            Instance.seekEnemyAction(zombie);
        }
    }

    /// <summary>
    /// Triggered by activating tower with "goo"
    /// </summary>
    public delegate void SpawnFighterZombieHandler();
    private SpawnFighterZombieHandler spawnFighterZombieAction;
    public static void SubscribeSpawnFighterZombie(SpawnFighterZombieHandler handler)
    {
        Instance.spawnFighterZombieAction += handler;
    }
    public static void UnsubscribeSpawnFighterZombie(SpawnFighterZombieHandler handler)
    {
        Instance.spawnFighterZombieAction -= handler;
    }
    public static void TriggerSpawnFighterZombie()
    {
        if (Instance.spawnFighterZombieAction != null)
        {
            Instance.spawnFighterZombieAction();
        }
    }

    /// <summary>
    /// Triggered when player goo level changes
    /// </summary>
    public delegate void GooLevelChangedHandler(int newLevel);
    private GooLevelChangedHandler gooLevelChangedAction;
    public static void SubscribeGooLevelChanged(GooLevelChangedHandler handler)
    {
        Instance.gooLevelChangedAction += handler;
    }
    public static void UnsubscribeGooLevelChanged(GooLevelChangedHandler handler)
    {
        Instance.gooLevelChangedAction -= handler;
    }
    public static void TriggerGooLevelChanged(int newLevel)
    {
        if (Instance.gooLevelChangedAction != null)
        {
            Instance.gooLevelChangedAction(newLevel);
        }
    }

    /// <summary>
    /// Triggered at Sunset
    /// </summary>
    public delegate void SunsetHandler();
    private SunsetHandler sunsetAction;
    public static void SubscribeSunset(SunsetHandler handler)
    {
        Instance.sunsetAction += handler;
    }
    public static void UnsubscribeSunset(SunsetHandler handler)
    {
        Instance.sunsetAction -= handler;
    }
    public static void TriggerSunset()
    {
        if (Instance.sunsetAction != null)
        {
            Instance.sunsetAction();
        }
    }

    /// <summary>
    /// Triggered at Sunrise
    /// </summary>
    public delegate void SunriseHandler();
    private SunriseHandler sunriseAction;
    public static void SubscribeSunrise(SunriseHandler handler)
    {
        Instance.sunriseAction += handler;
    }
    public static void UnsubscribeSunrise(SunriseHandler handler)
    {
        Instance.sunriseAction -= handler;
    }
    public static void TriggerSunrise()
    {
        if (Instance.sunriseAction != null)
        {
            Instance.sunriseAction();
        }
    }

    /// <summary>
    /// Triggered by player movement
    /// </summary>
    /// <param name="position">The updated position of the player after the move.</param>
    public delegate void PlayerMovedHandler(float position);
    private PlayerMovedHandler playerMovedAction;
    public static void SubscribePlayerMoved(PlayerMovedHandler handler)
    {
        Instance.playerMovedAction += handler;
    }
    public static void UnsubscribePlayerMoved(PlayerMovedHandler handler)
    {
        Instance.playerMovedAction += handler;
    }
    public static void TriggerPlayerMoved(float position)
    {
        if (Instance.playerMovedAction != null)
        {
            Instance.playerMovedAction(position);
        }
    }

    /// <summary>
    /// Triggered by camera movement
    /// </summary>
    /// <param name="position">The updated position of the camera after the move.</param>
    public delegate void CameraMovedHandler(float position);
    private CameraMovedHandler cameraMovedAction;
    public static void SubscribeCameraMoved(CameraMovedHandler handler)
    {
        Instance.cameraMovedAction += handler;
    }
    public static void UnsubscribeCameraMoved(CameraMovedHandler handler)
    {
        Instance.cameraMovedAction += handler;
    }
    public static void TriggerCameraMoved(float position)
    {
        if (Instance.cameraMovedAction != null)
        {
            Instance.cameraMovedAction(position);
        }
    }

    /// <summary>
    /// Triggered by user pausing the game;
    /// </summary>
    public delegate void GamePausedHandler();
    private GamePausedHandler gamePausedAction;
    public static void SubscribeGamePaused(GamePausedHandler handler)
    {
        Instance.gamePausedAction += handler;
    }
    public static void UnsubscribeGamePaused(GamePausedHandler handler)
    {
        Instance.gamePausedAction += handler;
    }
    public static void TriggerGamePaused()
    {
        if (Instance.gamePausedAction != null)
        {
            Instance.gamePausedAction();
        }
    }

    /// <summary>
    /// Triggered by user resuming the game;
    /// </summary>
    public delegate void GameResumedHandler();
    private GameResumedHandler gameResumedAction;
    public static void SubscribeGameResumed(GameResumedHandler handler)
    {
        Instance.gameResumedAction += handler;
    }
    public static void UnsubscribeGameResumed(GameResumedHandler handler)
    {
        Instance.gameResumedAction += handler;
    }
    public static void TriggerGameResumed()
    {
        if (Instance.gameResumedAction != null)
        {
            Instance.gameResumedAction();
        }
    }

}