#pragma once
#include "ActivityManager.h"

enum FrakjawEnemies {
    BoneWolf = 16191,
    BlackSmith = 14007,
    Marksman = 14008,
    Commando = 14009,
    MadScientist = 16511
};

enum FrakjawLots : LOT {
    ChestLOT = 16486,
    LedgedFrakjawLOT = 16289,
    LowerFrakjawLOT = 16048,
    CounterWeightLOT = 16141
};

struct FrakjawWaveEnemy {
    LOT lot;
    uint32_t largeNumber;
    uint32_t smallNumber;
};

class NjMonastryBossInstance : public ActivityManager {
public:
    void OnStartup(Entity* self) override;
    void OnPlayerLoaded(Entity* self, Entity* player) override;
    void OnPlayerExit(Entity* self, Entity* player) override;
    void OnActivityTimerDone(Entity *self, const std::string &name) override;
private:
    void StartFight(Entity* self);
    void WaveOver(Entity* self);
    void FightOver(Entity* self);
    void SummonWave(Entity* self, Entity* frakjaw);
    void LowerFrakjaw(Entity* self, Entity* frakjaw);
    void LowerFrakjawSummon(Entity* self, Entity* frakjaw);
    void RemovePoison(Entity* self);
    static void SpawnOnNetwork(Entity* self, const LOT& toSpawn, const uint32_t& numberToSpawn, const std::string& spawnerName);
    static void TeleportPlayer(Entity* player, uint32_t position);

    // Event handlers for anything spawned by the main spawner
    void HandleLedgedFrakjawSpawned(Entity* self, Entity* ledgedFrakjaw);
    void HandleCounterWeightSpawned(Entity* self, Entity* counterWeight);
    void HandleLowerFrakjawSpawned(Entity* self, Entity* lowerFrakjaw);
    void HandleWaveEnemySpawned(Entity* self, Entity* waveEnemy);
    void HandleWaveEnemyDied(Entity* self, Entity* waveEnemy);
    void HandleLowerFrakjawHit(Entity* self, Entity* lowerFrakjaw, Entity* attacker);
    void HandleLowerFrakjawDied(Entity* self, Entity* lowerFrakjaw);

    const std::vector<std::vector<FrakjawWaveEnemy>> m_Waves = {
        // Wave 1
        {
            { FrakjawEnemies::Marksman, 2, 1},
            { FrakjawEnemies::BlackSmith, 4, 3},
            { FrakjawEnemies::Commando, 2, 1},
            { FrakjawEnemies::MadScientist, 1, 0},
        },

        // Wave 2
        {
            { FrakjawEnemies::BoneWolf, 1, 0},
            { FrakjawEnemies::BlackSmith, 2, 2},
            { FrakjawEnemies::Marksman, 2, 1},
            { FrakjawEnemies::MadScientist, 1, 1},
        },

        // Wave 3
        {
            { FrakjawEnemies::BoneWolf, 2, 1},
            { FrakjawEnemies::Marksman, 2, 1},
            { FrakjawEnemies::Commando, 2, 2},
            { FrakjawEnemies::MadScientist, 1, 0},
        },

        // Wave 4
        {
            { FrakjawEnemies::BlackSmith, 2, 2},
            { FrakjawEnemies::BoneWolf, 1, 1},
            { FrakjawEnemies::Commando, 3, 1},
            { FrakjawEnemies::Marksman, 2, 0},
        },

        // Wave 5
        {
            { FrakjawEnemies::MadScientist, 1, 0},
            { FrakjawEnemies::BoneWolf, 2, 0},
            { FrakjawEnemies::Commando, 3, 0},
            { FrakjawEnemies::Marksman, 2, 0},
        }
    };

    const int32_t PoisonBuff = 60;

    // Variables
    const std::u16string TotalPlayersLoadedVariable = u"TotalPlayersLoaded";
    const std::u16string LargeTeamVariable = u"LargeTeam";
    const std::u16string FightStartedVariable = u"FightStarted";
    const std::u16string LedgeFrakjawVariable = u"LedgeFrakjaw";
    const std::u16string LowerFrakjawVariable = u"LowerFrakjaw";
    const std::u16string WaveNumberVariable = u"WaveNumber";
    const std::u16string OnLastWaveVarbiale = u"OnLastWave";
    const std::u16string TrashMobsAliveVariable = u"TrashMobsAlive";
    const std::u16string TotalAliveInWaveVariable = u"TotalAliveInWave";

    // Timers
    const char TimerSplitChar = '+';
    const std::string WaitingForPlayersTimer = "WaitingForPlayers";
    const std::string SpawnWaveTimer = "SpawnWave";
    const std::string SpawnNextWaveTimer = "SpawnNextWave";
    const std::string UnstunTimer = "Unstun+";
    const std::string FrakjawSpawnInTimer = "LowerFrakjawSpawnIn+";
    const std::string WaveOverTimer = "WaveOverTimer";
    const std::string FightOverTimer = "FightOver";
    const std::string LowerFrakjawCamTimer = "StartLowerFrakjawCam";
    const std::string SpawnCounterWeightTimer = "SpawnQB";
    const std::string SpawnRailTimer = "SpawnRailQB";
    const std::string SpawnLowerFrakjawTimer = "SpawnLowerFrakjaw";

    // Groups
    const std::string ChestSpawnpointGroup = "ChestSpawnPoint";

    // Spawner network names
    const std::string LedgeFrakjawSpawner = "LedgeFrakjaw";
    const std::string LowerFrakjawSpawner = "LowerFrakjaw";
    const std::string BaseEnemiesSpawner = "EnemySpawnPoints_";
    const std::string CounterweightSpawner = "Counterweights";
    const std::string FireRailSpawner = "FireRailActivatorQB";
    const std::string ExtraRocks = "ExtraRocks";

    // Cinematics
    const std::string LedgeFrakSummon = "FrakjawSummoning";
    const std::string BaseCounterweightQB = "CounterweightQB";
    const std::string BaseCounterweightSpawn = "CWQBSpawn";
    const std::string BottomFrakSummon = "BottomFrakjawSummoning";
    const std::string BottomFrakSpawn = "BottomFrakjawSpawning";
    const std::string TreasureChestSpawning = "TreasureChestSpawning";
    const std::string FireRailSpawn = "RailQBSpawn";

    // Notifications
    const std::u16string StopMusicNotification = u"StopMusic";
    const std::u16string StartMusicNotification = u"StartMusic";
    const std::u16string FlashMusicNotification = u"FlashMusic";
    const std::u16string PlayCinematicNotification = u"PlayCinematic";
    const std::u16string EndCinematicNotification = u"EndCinematic";

    // Animations
    const std::u16string SummonAnimation = u"summon";
    const std::u16string TeleportOutAnimation = u"teleport-out";
    const std::u16string TeleportInAnimation = u"teleport-in";
    const std::u16string StunnedAnimation = u"stunned";

    // Audio cues
    const std::string AudioWaveAudio = "Monastery_Frakjaw_Battle_";
    const std::string BattleOverAudio = "Monastery_Frakjaw_Battle_Win";
    const std::string CounterSmashAudio = "{d76d7b9d-9dc2-4e52-a315-69b25ef521ca}";
};
