#pragma once

#include "olcPixelGameEngine.h"
#include "olcPGEX_TransformedView.h"
#include "Constant.h"

struct Marker{
	size_t index;
	size_t size;
};

enum MemoryType{
	HEALTH,
	RANGE,
	ATKSPD,
	MOVESPD,
	PROCEDURE
};

struct Memory{
	MemoryType type;
	int size;
};

struct Unit{
public:
	Unit(std::vector<Memory>memory,vf2d pos,Renderable&img,bool friendly=false);
	int GetHealth();
	int GetRange();
	int GetAtkSpd();
	int GetMoveSpd();
	int GetProcedure();
	int GetMemorySize();
	std::vector<bool>memory;
	std::vector<bool>ghostMemory;
	void Update(float fElapsedTime);
	virtual void Attack(Unit&victim)=0;
	virtual void Draw(TileTransformedView&game);
	virtual void DrawHud(TileTransformedView&game);
	bool IsFriendly();
	bool IsSelected();
	void Select();
	void Deselect();
	vf2d GetPos();
	bool IsDead();
	vf2d GetUnitSize();
	void SetTargetUnit(std::weak_ptr<Unit>target);
	void SetTargetLocation(vf2d targetLoc);
	void SetPos(vf2d newPos);
	void AttemptAttack(Unit*unit);
	bool InFogOfWar();
	bool GhostInFogOfWar();
	void HideGhost();
	vf2d GetGhostPos();

	std::vector<bool>& operator <<=(const int n){
		for(int i=0;i<GetMemorySize()-1;i++){
			memory[i]=memory[i+1];
		}
		memory[GetMemorySize()-1]=0;
		if(!InFogOfWar()){
			ghostMemory=memory;
		}
		return memory;
	}

	std::vector<bool>& operator >>=(const int n){
		for(int i=GetMemorySize()-1;i>0;i--){
			memory[i]=memory[i-1];
		}
		memory[0]=0;
		if(!InFogOfWar()){
			ghostMemory=memory;
		}
		return memory;
	}
protected:
	bool friendly;
	Renderable&img;
	Marker health;
	Marker range;
	Marker atkSpd;
	Marker moveSpd;
	Marker procedure;
	std::weak_ptr<Unit>target;
	vf2d targetLoc=CONSTANT::UNSELECTED;
private:
	vf2d pos;
	vf2d ghostPos;
	int GetBits(Marker&m);
	bool selected=false;
	bool dead=false;
	bool InRange(std::shared_ptr<Unit>target);
	bool InRange(vf2d pos);
	float reloadTimer=0;
	void _Attack(Unit*finalTarget);
	vf2d movementVel={0,0};
	float changeDirTimer=0;
};

struct BasicUnit:Unit{
	BasicUnit(vf2d pos,Renderable&img,bool friendly=false);
	void Attack(Unit&victim)override;
};

struct BasicUnit2:Unit{
	BasicUnit2(vf2d pos,Renderable&img,bool friendly=false);
	void Attack(Unit&victim)override;
};