// ################################
// ##    Casova osa triggeru     ##
// ##     na udalosti ve hre     ##
// ################################

#pragma once
#ifndef TIME_AXIS_H
#define TIME_AXIS_H

#include "common.h"

#include <map>

#include "independent_constants.h"
#include "datetime.h"
#include "time_mapping.h"
#include "error_handling.h"
#include "threads.h"

using namespace std;

// ################################
// ################################

#define GAME_SECONDS_BETWEEN_GLOBAL_EVENTS 32 * GAME_TIME_TO_WALL_TIME_SPEED_RATIO

// ################################
// ################################

class triggerEventClass;
typedef     pair <dv_time::datetime,  triggerEventClass *> dateTimePTriggerEventClassPair;
typedef multimap <dv_time::datetime,  triggerEventClass *> dateTimePTriggerEventClassMap;
typedef      map <unsigned long long, dv_time :: datetime> ULLDateTimeMap;

#define MAX_TIME_AXIS_SEMAPHORE_VALUE 16777216

// ################################
// ################################

class timeAxis;
class timeAxisThread : public threads :: runnable
{
private:
    threads :: mutex mapLock_;
    threads :: semaphore semaphore_;
    volatile bool ending_;

    dateTimePTriggerEventClassMap   eventTriggers_;
    ULLDateTimeMap triggersToDateTime;         
    timeAxis *timeAxis_;
public:
    timeAxisThread();
    void setTimeAxis(timeAxis* ta) { timeAxis_ = ta; };
    void operator()(threads :: thread* thd);
    void pushEvent(dv_time:: datetime gametime, triggerEventClass* eventToInsert, 
        unsigned long long& lastTriggerID);
    void stop();
    void start();
};

// ################################
// ################################

class engine;
class timeAxis
{
private:
    threads :: thread *timeAxisThd_;
    timeAxisThread queue_;
    volatile bool active_;
    engine *engine_;
public:
    timeAxis();
    void setEngine(engine* eng);
    void start();
    void stop();
	void pushEventTrigger(dv_time::datetime triggerGameTime, triggerEventClass * triggerEvent, 
        unsigned long long& lastTriggerID);

    friend class timeAxisThread;
};

// ################################
// ################################

class triggerEventClass
{
private:
    unsigned long serverID;
    unsigned long long eventID;
public:
    virtual ~triggerEventClass() {};
    triggerEventClass();
    virtual void                   checkEvent() {};
            unsigned long          getServerID(void) const { return serverID; };
            unsigned long long     getEventID(void)  const { return eventID;  };
    virtual void                   DBInsert() {};
    virtual void                   DBDelete() {};

    virtual bool operator==(const triggerEventClass& tec) const;
    virtual bool operator!=(const triggerEventClass& tec) const;

    virtual std :: string          getEventName(void) const { return " --- not implemented --- "; }
};

// ################################
/*
class constructionDoneTriggerClass : public triggerEventClass
{
private:
	dtIdentifier fortressID_;
public:
    virtual ~constructionDoneTriggerClass() {};
	void checkEvent();
    virtual std :: string          getEventName(void) const { return "CONSTURCTION DONE"; }
};
*/
// ################################
/*
class outOfQuarkGluonPlasmaTriggerClass : public triggerEventClass
{
private:
	dtIdentifier fortressID_;
public:
    virtual ~outOfQuarkGluonPlasmaTriggerClass() {};
	void checkEvent();
    virtual std :: string          getEventName(void) const { return "OUT OF QUARK GLUON PLASMA"; }
};
*/
// ################################
/*
class outOfUlreaTriggerClass : public triggerEventClass
{
private:
	dtIdentifier fortressID_;
public:
    virtual ~outOfUlreaTriggerClass() {};
	void checkEvent();
    virtual std :: string          getEventName(void) const { return "OUT OF ULREA"; }
};
*/
// ################################
/*
class outOfHeavyWaterTriggerClass : public triggerEventClass
{
private:
	dtIdentifier fortressID_;
public:
    virtual ~outOfHeavyWaterTriggerClass() {};
	void checkEvent();
    virtual std :: string          getEventName(void) const { return "OUT OF HEAVY WATER"; }
};
*/
// ################################
/*
class outOfDeuteriumTriggerClass : public triggerEventClass
{
private:
	dtIdentifier fortressID_;
public:
    virtual ~outOfDeuteriumTriggerClass() {};
	void checkEvent();
    virtual std :: string          getEventName(void) const { return "OUT OF DEUTERIUM"; }
};
*/
// ################################
/*
class outOfZirconiumCrystalsTriggerClass : public triggerEventClass
{
private:
	dtIdentifier fortressID_;
public:
    virtual ~outOfZirconiumCrystalsTriggerClass() {};
	void checkEvent();
    virtual std :: string          getEventName(void) const { return "OUT OF ZIRCONIUM"; }
};
*/
// ################################
/*
class outOfEnergyTriggerClass : public triggerEventClass
{
private:
	dtIdentifier fortressID_;
public:
    virtual ~outOfEnergyTriggerClass() {};
	void checkEvent();
    virtual std :: string          getEventName(void) const { return "OUT OF ENERGY"; }
};
*/
// ################################
/*
class outOfIlmeniteTriggerClass : public triggerEventClass
{
private:
	dtIdentifier fortressID_;
public:
    virtual ~outOfIlmeniteTriggerClass() {};
	void checkEvent();
    virtual std :: string          getEventName(void) const { return "OUT OF ILMENITE"; }
};
*/
// ################################
/*
class outOfTitaniumTriggerClass : public triggerEventClass
{
private:
	dtIdentifier fortressID_;
public:
    virtual ~outOfTitaniumTriggerClass() {};
	void checkEvent();
    virtual std :: string          getEventName(void) const { return "OUT OF TITANIUM"; }
};
*/
// ################################
/*
class checkImpulsJetEngineShutDownTriggerClass : public triggerEventClass
{
private:
	dtIdentifier fortressID_;
public:
	checkImpulsJetEngineShutDownTriggerClass(dtIdentifier fortressID) { fortressID_ = fortressID; };
	virtual ~checkImpulsJetEngineShutDownTriggerClass() {};
	void checkEvent();
    virtual std :: string          getEventName(void) const { return "CHECK IMPULSE JET ENGINE SHUT DOWN"; }
};
*/
// ################################

class scientificAndMedicalPhaseGlobalTriggerClass : public triggerEventClass
{
public:
	scientificAndMedicalPhaseGlobalTriggerClass() {};
	virtual ~scientificAndMedicalPhaseGlobalTriggerClass() {};
	void checkEvent();
	virtual std::string getEventName(void) const { return "SCIENTIFIC AND MEDICAL PHASE"; };
	static void registerNextTriggerInstance();
};

// ################################

class shipMovementUpdate : public triggerEventClass
{
private:
    dv_time:: datetime eventTime_;
    dtIdentifier shipId_;
public:
    shipMovementUpdate(dv_time:: datetime eventTime, dtIdentifier shipId) { eventTime_ = eventTime, shipId_ = shipId; };
    virtual ~shipMovementUpdate() {};
	virtual void checkEvent();
    virtual std :: string          getEventName(void) const { return "SHIP MOVEMENT"; }
};

// ################################

class quarkGluonPlasmaUpdateTriggerClass : public triggerEventClass
{
private:
	dtIdentifier fortressID_;
public:
	quarkGluonPlasmaUpdateTriggerClass(dtIdentifier fortressID) { fortressID_ = fortressID; };
	virtual ~quarkGluonPlasmaUpdateTriggerClass() {};
	void checkEvent();
    virtual std :: string          getEventName(void) const { return "UPDATE QUARK GLUON PLASMA"; }
};

// ################################

class energyDistributionPhaseAndWeaponFireTriggerClass : public triggerEventClass
{
private:
	dtIdentifier fortressID_;
public:
	energyDistributionPhaseAndWeaponFireTriggerClass(dtIdentifier fortressID) { fortressID_ = fortressID; };
	virtual ~energyDistributionPhaseAndWeaponFireTriggerClass() { };
	void checkEvent();
    virtual std :: string          getEventName(void) const { return "ENERGY DISTRIBUTION PHASE"; }
};

// ################################

class containeredResourcesUpdateTriggerClass : public triggerEventClass
{
private:
	dtIdentifier fortressID_;
public:
	containeredResourcesUpdateTriggerClass(dtIdentifier fortressID) { fortressID_ = fortressID; };
	virtual ~containeredResourcesUpdateTriggerClass() {};
	void checkEvent();
    virtual std :: string          getEventName(void) const { return "CONTAINERED RESOURCES UPDATE"; }
};

// ################################

class checkConstructionTriggerClass : public triggerEventClass
{
private:
	dtIdentifier fortressID_;
	dtIdentifier hangarID_;
public:
	checkConstructionTriggerClass(dtIdentifier fortressID, dtIdentifier hangarID) { fortressID_ = fortressID; hangarID_ = hangarID; };
	virtual ~checkConstructionTriggerClass() {};
	void checkEvent();
    virtual std :: string          getEventName(void) const { return "CHECK CONSTRUCTION"; }
};

// ################################
// ################################

#endif