/*******************************************************************************
*                                                                              *
* Société de Transports de Montréal.                                    	   *
* 2012                                                                         *
*                                                                              *
* Projet Zones Tests                                                           *
*                                                                              *
*                                                                              *
*                                                                              *
*******************************************************************************/
/*
	Description:
	Description du fichier si nécessaire.
	
*/

/* ************************************************************************** */
/* Revision:
### YYYMMDD JFM
	Verision d'origine.
	
### YYYYMMDD Description du besoin ou du bug
	Description du changement.
 */

/* ************************************************************************** */

#ifndef ZTSTATEMACHINE_H
#define ZTSTATEMACHINE_H

#include "GlobalDefine.h"
#include <QObject>
#include "ZTData.h"
#include "Station.h"
#include "ZTPage.h"
#include "PCIIOMgr.h"
#include "ZT1AnalysisThread.h"
#include "ZT2AnalysisThread.h"
#include <QThread>
#include <QElapsedTimer>
#include <AbstractLazerProbe.h>
#include "TKGenerator.h"
#include "LogMgr.h"
#include "InputModule.h"
#include "MixedModule.h"
//#include "ModbusRepository.h"
#include "TKTransportInterface.h"
#include "ModbusCCMgr.h"
#include "NetDriveMgr.h"


#define ZT_SM_DEFAULT_LOG_DELAY 10 //millilseconds
#define ZT1_MAX_PASSAGE_DELAY (qint64)300000 //milliseconds = 5 minutes
#define ZT2_MAX_PASSAGE_DELAY (qint64)300000 //milliseconds = 5 minutes

class CZTSimulator;

//États de la machine à état générale
enum eZTSMStates
{
	ZT_INIT_STATE,
	ZT_EXECUTE_STATE
};
enum eZTSMEvents
{
	ZT_TICK_EVENT
};

//états de la machine à états de la ZT1
enum eZT1SMStates
{
	ZT1_WAIT_FOR_CI_STATE,
	ZT1_WAIT_FOR_TRAIN_STATE,
	ZT1_TRAIN_ON_APPROACH_CDV_STATE,
    ZT1_WAIT_FOR_SUBSEQUENT_LIBERATION,
	ZT1_ANALYZE_TRAIN_STATE,
//	ZT1_WAIT_FOR_ZT1_LIBERATION_STATE,
	ZT1_POST_DETECTION_STATE
};

//états de la machine à états ZT2
enum eZT2SMStates
{
	ZT2_WAIT_FOR_CI_STATE,
    ZT2_WAIT_FOR_APPROACH_LIBERATION_STATE,
    ZT2_WAIT_FOR_TRAIN_STATE,
	ZT2_ANALYZE_TRAIN_STATE,
    ZT2_WAIT_FOR_CDV_LIBERATION_STATE,
    ZT2_POST_DETECTION_STATE
};

enum ePostDetectionRet
{
	RET_POST_DETECTION_VALID,
	RET_POST_DETECTION_WORK_VEHICLE,
    RET_POST_DETECTION_FALSE_OCCUPATION,

	RET_POST_DETECTION_MAX_RET
};

class CZoneTest;

class CZTStateMachine : public QObject
{
	Q_OBJECT
public:
    explicit CZTStateMachine(CZoneTest *ZTPtr,QObject *parent = 0);
	~CZTStateMachine();
	unsigned int ZTStateMachine(unsigned int Event, unsigned int SubEvent = 0);		//Exécution de la SM principale
    void BindPointers(CStation *ptr,CInputModule *InputModule,COutputModule *OutputModule,CZTPage *ZTPagePTr,CPCIIOMgr *PCIIOPtr,CAbstractLazerProbe *PGIntProbePtr, CAbstractLazerProbe *PGExtProbePTr,CLogMgr *LogMgr,CTKTransportInterface *TKTransport,CZTSimulator *ZTSimPtr = 0,CAnalogInputModule *DataQInterface = 0); //Assignation de pointeurs
    void BindModbusCCMgrPtr(CModbusCCMgr *ModbusCCPtr);
 //   void BindNetworkDrivePtr(CNetDriveMgr *mNetDrivePtr);

	CZTDetectionFunctionConfig *mZTDetectionConfig;
    CTKGenerator *mTKGenerator;		//pointeur vers la classe qui gère les alarmes au PCC

	void SetZT2Presence(bool Presence);

	void SetAutoExportZT1CSV(bool Export){mAutoExportZT1CSV = Export;}
	void SetAutoExportZT2CSV(bool Export){mAutoExportZT2CSV = Export;}

	bool IsZT1Active();
	bool IsZT2Active();
	bool EnterPGCalibrationMode(int NbPassages);
	bool QuitPGCalibrationMode();
	unsigned int EnterMaintenanceMode();
	unsigned int QuitMaintenanceMode();
    unsigned int ClearMaintenanceCurrentTK();
    void SetLogResolution(bool HighResON);
	unsigned int SetPGTreshold(qint32 PGTreshold);
	void ResetNbTriggers();
    void ResetNbPassages();


	unsigned int SendTKToPCC(int DetectionID, int Rank);

    unsigned int GetNbPassages(){return mNbPassages;}
    unsigned int GetNbTriggers(){return mNbTriggers;}
    unsigned int GetZT1ActiveStatus(){return mZT1ActiveStatus;}
    unsigned int GetZT2ActiveStatus(){return mZT2ActiveStatus;}
    bool IsInMaintenance(){return mIsMaintenanceModeON;}
    bool IsInPGCalibration(){return mIsPGCalibON;}

private:
	unsigned int ZT1StateMachine(unsigned int Event, unsigned int SubEvent = 0);
	unsigned int ZT2StateMachine(unsigned int Event, unsigned int SubEvent = 0);

    unsigned int InsertZT1LogItem(CZT1ThreadData *ThreadData = 0,int SDFReading = 0);
	unsigned int DestroyZT1Log();
    unsigned int InsertZT2LogItem(CZT2ThreadData *ThreadData = 0);
    unsigned int DestroyZT2Log();
	unsigned int SaveZT1EventsLog(CZT1Log *Log);
    unsigned int SaveZT2EventsLog(CZT2Log *Log);
	unsigned int DestroyCalibrationData();
	unsigned int ComputePGCalibration();
	unsigned int AnalyzeZT1PostDetection();
	unsigned int AnalyzeZT2PostDetection();

	void ClearZT1DetectionsList();



	unsigned int mZT1State;
	unsigned int mZT2State;
	unsigned int mZTState;
	unsigned int mPGCalibState;


	bool mCIZT1Active;
    bool mCIZT2Active;
	bool mIsPGCalibON;
	bool mIsMaintenanceModeON;
	bool mMaintenancePPIZT1Latch, mMaintenancePPEZT1Latch, mMaintenancePPIZT2Latch, mMaintenancePPEZT2Latch;
	int mAnalogReading;


    CZoneTest *mProgramPtr;
	CStation *mZTStationPtr;
	CAnalogInputModule *mSDFAnalogMonitorInterface;
	CInputModule *mInputModule;
   // CModbusRepository *mCCModbusRepo;
    CModbusCCMgr *mModbusCCMgr;
 //   CNetDriveMgr *mNetworkDriveMgr;


	CPCIIOMgr *mPCIIOPtr;
	CAbstractLazerProbe *mPGIntProbePtr;
	CAbstractLazerProbe *mPGExtProbePtr;

//	QList<CCDV*> *mCDVListPtr;	//Pointeur vers la liste des CDV
	CZTPage *mZTPagePTr;
	CZTSimulator *mZtSimPtr;
	GenericInputMasks_t *mZTInputMasks;

	CZT1AnalysisThread *mZT1WorkerThread;	//Thread haute fréquence qui analyse le passage en ZT1
	QThread *mZT1SMThread;

	CZT2AnalysisThread *mZT2WorkerThread;	//Thread haute fréquence qui analyse le passage en ZT2
	QThread *mZT2SMThread;

	QElapsedTimer mEventsRefTimer;		//Cafeful, this timer is shared with the thread.  DO NOT access it while the ZT1 or ZT2 thread is running.
	QElapsedTimer mZT1LogDelayTimer;	//Timer qui limite la fréquence d'écriture dans le log.  On peut bypasser en cochant "log haute fréquence" dans la page ingénierie
	QElapsedTimer mZT1PassageTimeLimitTimer;
	QElapsedTimer mZT2PassageTimeLimitTimer;
	qint64 mLogDelay;
	CLogMgr *mLogMgr;					//Classe qui gère les logs.

	unsigned int mLastInputs, mCurInputs;	//Latch des entrées discrètes

	unsigned int mNbPassages;				//Nombre de passages
	unsigned int mNbTriggers;				//Nombre de déclenchements
    unsigned int mTrainTypeDetected, mZT2TrainType;		//Type de train
	unsigned int mCalibrationPassagesCount;	//Nombre de passages lors de la calibration
	unsigned int mPGNbTotalPassages;		//Nombre de passages requis lors de la calibration
	unsigned int mZT1ActiveStatus;		//état de la ZT1 (Active ou pas)
	unsigned int mZT2ActiveStatus;		//état de la ZT2 (Active ou pas)
	bool mZT2Present;		//Flag qui indique si la station possède une ZT2
	bool mAutoExportZT1CSV,mAutoExportZT2CSV;	//Flags qui indiquent s'il faut créer des fichiers CSV pour chaque log.  Configurable dans la page ingénierie.
    unsigned int mZT1PEQType;   //Type de la dernière panne équipement lorsqu'il y en a une.
    QList<qint16> mZT1TrainComposition; //Composition du train franchissant ZT1 (obtenue par Modbus)
    QList<qint16> mZT2TrainComposition; //Composition du train franchissant ZT2 (obtenue par Modbus)

	CZT1Log mZT1Log;							//Les données du log ZT1 du passage courant (un seul train)
    CZT2Log mZT2Log;
    //QVector<CZT2LogData*>mZT2Log;					//Les données du log ZT2 du passage courant (un seul train)
	QVector<CZTDetectionData*> mZT1DetectionsLog;	//Log des déclenchements ZT1
	QVector<CZTDetectionData*> mZT2DetectionsLog; //Log des déclenchements ZT2
	QList<CZTPGCalibrationData*> mZTPGCalibrationData[ZT_SM_MAX_NB_PG_CALIB_PASSAGES]; //Données de calibration

    QElapsedTimer mFSSyncTimer;
    bool mTimeToForceSyncFS;

    QDateTime mZTActivationDateTime;

signals:
	void PGCalibrationFinished(int);		//Signal envoyé lorsque la calibration est terminée. Le paramètre est la valeur calculée.
	void PGCalibrationStatus(int,int);		//Signal envoyé pour informer de l'état de la calibration.  Le paramètre 1 est le nombre de passages à date et le 2è est le nombre requis.
	void MaintenancePPActivated(unsigned int);		//Signal envoyé à la page d'entretien pour indiquer qu'une pédale PP a été activée.
    void NewTrainLogSaved(QString Filename, bool Detection);        //Signal envoyé pour notifier l'interface graphique qu'un nouveau fichier de passage a été sauvegardé.

public slots:

    void ZT1StateChanged(CZT1ThreadData*, bool, int);	//Envoyé par le thread ZT1 lorsque des nouvelles données sont prêtes à ajouter au log
	void ZT2StateChanged(CZT2ThreadData* );			//Envoyé par le thread ZT2 lorsque des nouvelles données sont prêtes à ajouter au log
	void ZT1NewDetection(CZTDetectionData* );		//Envoyé par le thread ZT1 lorsqu'un déclenchement survient
	void ZT1NewFlag(int, CZT1FlagsData*);			//Envoyé par le thread ZT1 lorsqu'un flag est disopnible
	void ZT2NewDetection(CZTDetectionData* );		//Envoyé par le thread ZT1 lorsqu'un déclenchement survient
	void NewPGCalibrationData(CZTPGCalibrationData*);	//Envoyé par le thread ZT1 lorsque des données de calibration sont disponibles.
	void AddLogStringFromThread(QString);
    void ModbusCCANUpdate();                       //Envoyé par ModbusCCMgr lorsque la CC change la valeur du signal AN1 ou AN2 via le Modbus.


	
};

#endif // ZTSTATEMACHINE_H
