#include <iostream>
#include <string>
#include <atomic>
using namespace std;

namespace SpaceFleet{
	template<class T>
	class Coordinates{
		public:
			T x, y, z;
			Coordinates(T startX=0,T startY=0,T startZ=0){
				x=startX;
				y=startY;
				z=startZ;
			}
	};

	class Starship{
		private:
			string name;
			int maxSpeed;
			int* shieldLevels;
			int shieldCount;
		public:
			static int totalActiveShips;
			Starship(string shipName="Unknown Ship",int speed=100){
				name=shipName;
				maxSpeed=speed;
				shieldCount=3;
				shieldLevels=new int[shieldCount];
				for(int i=0;i<shieldCount;i++){
					shieldLevels[i]=100;
				}
				totalActiveShips++;
				cout<<"[+] Adding ship completed: "<<name<<endl;
			}
			Starship(const Starship& other){
				this->name=other.name+" (Clone)";
				this->maxSpeed=other.maxSpeed;
				this->shieldCount=other.shieldCount;
				this->shieldLevels=new int[this->shieldCount];
				for(int i=0;i< this->shieldCount;i++){
					this->shieldLevels[i]=other.shieldLevels[i];
				}
				totalActiveShips++;
				cout<<"[C] Cloning ship: "<< this->name<<endl;
			}
			~Starship(){
				cout<<"[-] Destroying ship: "<<name<<". Clearing shield memory."<<endl;
				delete[] shieldLevels;
				totalActiveShips--;
			}
			string getName(){return name;}
			inline void takeDamage(int damage){
				if(shieldCount>0&&shieldLevels[0]>0){
					shieldLevels[0]-=damage;
					if(shieldLevels[0]<0) shieldLevels[0]=0;
				}
			}
			void printStatus();
	};

	int Starship::totalActiveShips=0;

	void Starship::printStatus(){
		cout<<"  -> Ship: "<<name<<" | Speed: "<<maxSpeed<<" | Front Shield: ";
		if(shieldCount>0) cout<<shieldLevels[0]<<"%";
		cout<<endl;
	}

	class FleetHeadquarters{
		private:
			FleetHeadquarters(){
				cout<<"\nThe fleet headquarters were established!"<<endl;
			}
			FleetHeadquarters(const FleetHeadquarters&)=delete;
			FleetHeadquarters& operator=(const FleetHeadquarters&)=delete;
			static FleetHeadquarters* instance;
		public:
			volatile bool redAlert=false;
			atomic<int> enemiesDestroyed{0};
			static FleetHeadquarters* getInstance(){
				if(instance==nullptr){
					instance=new FleetHeadquarters();
				}
				return instance;
			}
			void triggerRedAlert(){
				redAlert=true;
				cout<<"!!! [EMERGENCY] Headquarters signalled RED ALERT!!!\n"<<endl;
			}
			void reportKill(){
				enemiesDestroyed++;
			}
	};

	FleetHeadquarters* FleetHeadquarters::instance=nullptr;

	auto calculateCombatDistance(double x1, double y1, double x2, double y2){
		auto dx=x2-x1;
		auto dy=y2-y1;
		decltype(dx) distanceSq=(dx*dx)+(dy*dy);
		return distanceSq;
	}
}

#include <ctime>
using namespace SpaceFleet;

int main(){
	cout<<"\n==================================================="<<endl;
	cout<<"   [***] SPACE FLEET COMMAND SIMULATOR v1.0 [***]    "<<endl;
	cout<<"===================================================\n"<<endl;
	Coordinates<double> earth(0.0,0.0,0.0);
	Coordinates<double> enemySector(4.37,10.5,-2.2);
	cout<<"Earth: ("<<earth.x<<", "<<earth.y<<", "<<earth.z<<")"<<endl;
	cout<<"Enemy Sector: ("<<enemySector.x<<", "<<enemySector.y<<", "<<enemySector.z<<")\n"<<endl;
	Starship enterprise("USS Enterprise",250);
	Starship voyager("USS Voyager",200);
	Starship defiant=enterprise;
	cout<<">>> Total Active Ships in Sector (Static): "<<Starship::totalActiveShips<<" <<<\n"<<endl;
	FleetHeadquarters* hq=FleetHeadquarters::getInstance();
	auto combatDist=calculateCombatDistance(earth.x,earth.y,enemySector.x,enemySector.y);
	cout<<"Calculated Combat Distance: "<<combatDist<<" parsecs^2"<<endl;
	hq->triggerRedAlert();
	clock_t startTime=clock();
	cout<<"[SIMULATION] Fire exchange in process... Please wait..."<<endl;
	for(long long i=0;i<50000000;i++){
		if(i%10000000==0){
			enterprise.takeDamage(15);
			voyager.takeDamage(5);
			hq->reportKill();
		}
	}
	clock_t finishTime=clock();
	double combatDuration=double(finishTime-startTime)/CLOCKS_PER_SEC;
	cout<<"\n=================================================="<<endl;
	cout<<"              [***] FIGHT STATUS [***]              "<<endl;
	cout<<"=================================================="<<endl;
	enterprise.printStatus();
	voyager.printStatus();
	defiant.printStatus();
	cout<<"\nConfirmed Hits: "<<hq->enemiesDestroyed<<endl;
	cout<<"Fight Duration: "<<combatDuration<<" seconds.";
	cout<<"\n[SYSTEM]: Termination. Auto memory clean-up follows..."<<endl;
	return 0;
}


