#pragma once
#include <regex>
#include "ActivityManager.h"

struct SGEnemy {
	std::vector<std::string> spawnPaths{};
	LOT lot;
	float_t minSpawnTime;
	float_t maxSpawnTime;
	bool respawns;
	float_t minRespawnTime;
	float_t maxRespawnTime;
	float_t initialSpeed;
	int32_t score;
	bool changeSpeedAtWaypoint;
	float_t speedChangeChance;
	float_t minSpeed;
	float_t maxSpeed;
	bool isMovingPlatform;
	bool despawnOnLastWaypoint;
};

struct SGConstants {
	Vector3 playerStartPosition;
	Quaternion playerStartRotation;
	LOT cannonLot;
	uint32_t impactSkillID;
	LOT projectileLot;
	Vector3 playerOffset;
	uint32_t rewardModelMatrix;
	float_t cannonVelocity;
	float_t cannonMinDistance;
	float_t cannonRefireRate;
	Vector3 cannonBarrelOffset;
	LOT cannonSuperchargedProjectileLot;
	LOT cannonProjectileLot;
	uint32_t cannonSuperChargeSkill;
	uint32_t cannonSkill;
	int32_t cannonTimeout;
	float_t cannonFOV;
	bool useLeaderboards;
	uint32_t streakModifier;
	uint32_t chargedTime;
	uint32_t chargedPoints;
	std::string rewardModelGroup;
	uint32_t activityID;
	std::map<std::string, uint32_t> scoreRewards;
	uint32_t scoreLootMatrix1;
	uint32_t scoreLootMatrix2;
	uint32_t scoreLootMatrix3;
	uint32_t scoreLootMatrix4;
	uint32_t scoreLootMatrix5;
	float_t firstWaveStartTime;
	float_t inBetweenWavePause;
};

class SGCannon : public ActivityManager {
public:
	void OnStartup(Entity* self) override;
	void OnPlayerLoaded(Entity* self, Entity* player) override;
	void OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2, int32_t param3) override;
	void OnActivityStateChangeRequest(Entity* self, LWOOBJID senderID, int32_t value1, int32_t value2, const std::u16string& stringValue) override;
	void OnMessageBoxResponse(Entity* self, Entity* sender, int32_t button, const std::u16string& identifier, const std::u16string& userData) override;
	void OnActivityTimerDone(Entity* self, const std::string& name) override;
	void OnActivityTimerUpdate(Entity* self, const std::string& name, float_t timeRemaining, float_t elapsedTime) override;
	void OnRequestActivityExit(Entity* self, LWOOBJID player, bool canceled) override;
	void OnActivityNotify(Entity* self, GameMessages::ActivityNotify& notify) override;
	void OnShootingGalleryFire(Entity& self, GameMessages::ShootingGalleryFire& fire) override;
	void SuperChargeTimerFunc(Entity* self);
	void SpawnWaveTimerFunc(Entity* self);
	void EndWaveTimerFunc(Entity* self);
	void GameOverTimerFunc(Entity* self);
	void DoSpawnTimerFunc(Entity* self, const std::string& name);
	void EndGameBufferTimerFunc(Entity* self);
private:
	static std::vector<std::vector<SGEnemy>> GetWaves();
	static SGConstants GetConstants();
	void ResetVars(Entity* self);
	void StartGame(Entity* self);
	void DoGameStartup(Entity* self);
	void SpawnNewModel(Entity* self);
	void TimerToggle(Entity* self, bool start = false);
	void SpawnObject(Entity* self, const SGEnemy& toSpawn, bool spawnNow = false);
	void StartChargedCannon(Entity* self, uint32_t optionalTime = 0);
	void ToggleSuperCharge(Entity* self, bool enable);
	void RecordPlayerScore(Entity* self);
	void PlaySceneAnimation(Entity* self, const std::u16string& animationName, bool onCannon, bool onPlayer, float_t priority);
	static void RemovePlayer(LWOOBJID playerID);
	void PauseChargeCannon(Entity* self);
	void StopGame(Entity* self, bool cancel = false);
	void RegisterHit(Entity* self, Entity* target, const std::string& timerName);
	void UpdateStreak(Entity* self);
	float_t GetCurrentBonus(Entity* self);

	LOT m_CannonLot = 1864;
	std::u16string PlayerIDVariable = u"PlayerID";
	std::u16string HideScoreBoardVariable = u"HideScoreBoard";
	std::u16string ReSetSuperChargeVariable = u"ReSetSuperCharge";
	std::u16string ShowLoadingUI = u"showLoadingUI";
	std::u16string SpawnNumberVariable = u"SpawnNum";
	std::u16string CurrentSpawnNumberVariable = u"CurSpawnNum";
	std::u16string ThisWaveVariable = u"ThisWave";
	std::u16string GameScoreVariable = u"GameScore";
	std::u16string GameTimeVariable = u"GameTime";
	std::u16string GameStartedVariable = u"GameStarted";
	std::u16string ShotsFiredVariable = u"ShotsFired";
	std::u16string MaxStreakVariable = u"MaxStreak";
	std::u16string MissesVariable = u"Misses";
	std::u16string CurrentStreakVariable = u"CurrentStreak";
	std::u16string CurrentSuperChargedTimeVariable = u"CurrentSuperChargedTime";
	std::u16string StreakBonusVariable = u"StreakBonus";
	std::u16string LastSuperTotalVariable = u"LastSuperTotal";
	std::u16string CurrentRewardVariable = u"CurrentReward";
	std::u16string RewardsVariable = u"Rewards";
	std::u16string TotalScoreVariable = u"TotalScore";
	std::u16string InitVariable = u"Init";
	std::u16string ImpactSkillVariale = u"ImpactSkill";
	std::u16string PlayerScoresVariable = u"PlayerScores";
	std::u16string InitialVelocityVariable = u"InitialVelocity";
	std::u16string ValidActorsVariable = u"ValidActors";
	std::u16string ValidEffectsVariable = u"ValidEffects";
	std::u16string SuperChargeActiveVariable = u"SuperChargeActive";
	std::u16string MatrixVariable = u"Matrix";
	std::u16string TimeLimitVariable = u"game_timelimit";
	std::u16string AudioStartIntroVariable = u"Audio_Start_Intro";
	std::u16string ClearVariable = u"Clear";
	std::u16string FirstTimeDoneVariable = u"FirstTimeDone";
	std::u16string RewardAddedVariable = u"rewardAdded";
	std::u16string SuperChargePausedVariable = u"Super_Charge_Paused";
	std::u16string WaveStatusVariable = u"WaveStatus";
	std::u16string CountVariable = u"count";
	std::u16string StopVariable = u"Stop";
	std::u16string ActiveSpawnsVariable = u"ActiveSpawns";
	std::u16string SpawnedObjects = u"SpawnedObjects";
	std::u16string WaveNumVariable = u"wave.waveNum";
	std::u16string WaveStrVariable = u"wave.waveStr";
	std::u16string ChargeCountingVariable = u"charge_counting";
	std::u16string SuperChargeBarVariable = u"SuperChargeBar";
	std::u16string NumberOfChargesVariable = u"NumberOfCharges";
	std::u16string CannonBallSkillIDVariable = u"cbskill";
	std::u16string HideSuperChargeVariable = u"HideSuper";
	std::u16string AudioFinalWaveDoneVariable = u"Audio_Final_Wave_Done";
	std::u16string ModelPercentVariable = u"modelPercent";

	std::string SpawnWaveTimer = "SpawnWave";
	std::string EndWaveTimer = "EndWave";
	std::string GameOverTimer = "GameOver";
	std::string DoSpawnTimer = "DoSpawn";
	std::string EndGameBufferTimer = "endGameBuffer";
	std::string SuperChargeTimer = "SuperChargeTimer";

	std::string ModelToBuildEvent = "modelToBuild";

	std::regex DoSpawnRegex = std::regex("\\d*");
	SGConstants constants{};
	std::vector<std::vector<SGEnemy>> m_Waves{};
};
