#pragma once
#include "olcPixelGameEngine.h"
#include "olcSoundWaveEngine.h"
#include "olcPGEX_TransformedView.h"
#include "olcPGEX_AudioListener.h"
#include "olcPGEX_AudioSource.h"
#include "olcPGEX_SplashScreen.h"
#include "olcPGEX_QuickGUI.h"
#include "Unit.h"
#include "Constant.h"
#include "Image.h"
#include "DeathAnimation.h"
#include "Sound.h"
#include "DebuffIcon.h"
#include "CollectionPoint.h"
#include "Resources.h"
#include "Textbox.h"
#include "Level.h"
#include "GameFlags.h"
#include "GameState.h"

struct Letter{
	vf2d pos;
	float spd;
	char c;
};

class VirusAttack : public olc::PixelGameEngine
{
public:
	#ifdef SPLASH_ENABLED
		SplashScreen splash;
	#endif
	vi2d WORLD_SIZE={64,64};

	std::vector<std::shared_ptr<Unit>>queuedUnits;
	std::vector<std::shared_ptr<Unit>>units;
	std::vector<std::shared_ptr<CollectionPoint>>collectionPoints;
	std::vector<std::unique_ptr<DeathAnimation>>deathAnimations;
	std::vector<DebuffIcon>debuffIcons;
	std::vector<ResourceGainIcon>resourceGainIcons;

	olcPGEX_AudioListener AL;
	Audio*bgm=nullptr;

	Resources player_resources,player_prev_resources,player_display_resources,enemy_resources;

	TileTransformedView gametv;

	Textbox unitCreationBox,testBox,memoryAllocatorBox,platformCreationBox,restartBox;
	Level*currentLevel;

	std::map<LevelName,Level>levelData;

	QuickGUI::Manager mainMenu;
	QuickGUI::TransparentButton*campaignStartButton;
	QuickGUI::TransparentButton*audioToggleButton;
	QuickGUI::TransparentButton*difficultyToggleButton;
	QuickGUI::TransparentButton*creditsButton;
	QuickGUI::TransparentButton*exitGameButton;
	QuickGUI::Manager restartManager;
	QuickGUI::TransparentImageButton*restartButton;
	QuickGUI::Manager unitCreationList;
	QuickGUI::ImageButton*leftShifterButton;
	QuickGUI::ImageButton*rightShifterButton;
	QuickGUI::ImageButton*bitRestorerButton;
	QuickGUI::ImageButton*memorySwapperButton;
	QuickGUI::ImageButton*corrupterButton;
	QuickGUI::ImageButton*platformButton;
	QuickGUI::Manager platformCreationList;
	QuickGUI::ImageButton*ramBankButton;
	QuickGUI::ImageButton*refresherButton;
	QuickGUI::ImageButton*turretButton;
	QuickGUI::ImageButton*memoryGuardButton;

	float matrixTimer=0;
	float updatePixelsTimer=0;
	const std::array<char,16>matrixLetters={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F',};
	std::vector<Letter>activeLetters;
	std::array<float,5>resourceGainTimer={0};
	std::array<float,5>resourceDisplayValueUpdateTimer={0};
	std::array<bool,5>resourceIncreased={false};
	std::array<int,5>playerUsedMemory={0},enemyUsedMemory={0};
	std::array<int,5>playerUsedDisplayMemory={0},enemyUsedDisplayMemory={0};
	float lastDisplayMemoryUpdateTimer=0;
	int lastTotalMemory=0;
	int memoryDisplayAmt=0;
	float memoryDisplayDelay=0;
	bool memoryIncreased=true;
	float memoryChangeTimer=2;
	float levelForegroundFade=0;
	LevelName levelToLoad;
	bool reloadLevel=false;
	bool restartButtonHeldDown=false;
	float restartButtonHoldTime=0;
	GameState state=GameState::MAIN_MENU;
	float nextColorChange=10;
	std::array<Pixel,7>colorChangeOptions={VERY_DARK_BLUE,VERY_DARK_CYAN,VERY_DARK_GREEN,VERY_DARK_GREY,VERY_DARK_MAGENTA,VERY_DARK_RED,VERY_DARK_YELLOW};
	Pixel currentBackCol;
	Pixel newCol;
	float transition=0;
	float flickerAmt=1;
	float arrowScroll=0;
	Renderable attackingLineModified;
	Renderable titleScreenText;
	float titleScreenY=-200;
	float textOrientationY=0;
	float textOrientationX=0;
	int currentScenario=0;
	GameFlags flags;
	float flashTimer=0;

	std::string objective="";

	vf2d randomBackgroundOffset;

	vf2d startingDragPos=CONSTANT::UNSELECTED;
	void HandleGUIDisplay();
	void HandleDraggingSelection();
	void DrawSelectionRectangle();
	void HandleRightClickMove();
	void CollisionChecking(std::shared_ptr<Unit>u,std::shared_ptr<Unit>u2);
	void IdentifyClosestTarget(std::weak_ptr<Unit>&closestUnit,float&closestDist,std::shared_ptr<Unit>u,std::shared_ptr<Unit>u2);
	vf2d GetWorldMousePos();
	void HandlePanAndZoom(float fElapsedTime);
	void DrawMinimap();
	void HandleMinimapClick();
	void InitializeImages();
	void UpdateMatrixTexture(float fElapsedTime);
	void RenderCollectionPoints(CollectionPoint*cp);
	void RenderFogOfWar();
	void InitializeSounds();
	void DrawResourceBar(float fElapsedTime);
	bool UnitCreationClickHandled();
	void InitializeGUIs();
	bool CanAfford(Resources&resources,std::vector<Memory>&unitCosts);
	void ExpendResources(Resources&resources,std::vector<Memory>&unitCosts);
	void UpdateUnitCreationListGUI(bool allocatorSelected);
	void LoadLevel(LevelName level);
	void InitializeLevelData();
	void UpdatePlatformCreationListGUI(bool platformSelected);
	int GetTotalUsedMemory();
	int GetPlayerUsedMemory();
	int GetEnemyUsedMemory();
	void DrawSystemMemoryBar(float fElapsedTime);
	void CalculateUsedMemory();
	void InitializeScenarios();
	void PerformLevelTransition(float fElapsedTime);
	void RestartLevel();
	void HandleRestartButton(float fElapsedTime);
	void DrawCurvedTexture(vf2d offset,vf2d size,Decal*decal,vf2d texOffset,Pixel col=WHITE,float curveThickness=0.8);

public:
	VirusAttack();

public:
	bool OnUserCreate() override;

	bool OnUserUpdate(float fElapsedTime) override;
	bool OnUserDestroy() override;
};