/*******************************************************************************
*                                                                              *
* Société de Transports de Montréal.                                    	   *
* 2012                                                                         *
*                                                                              *
* Projet Zones Tests                                                           *
*                                                                              *
*                                                                              *
*                                                                              *
*******************************************************************************/
/*
    Description:
	Cette classe est considérée comme l'instance du programme qui
    initialise et démarre tous les objets nécessaires.
    Elle assure aussi la synchronisation de ces derniers à l'aide de sa
    machine à états.
    
*/

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

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

#include "Zonetest.h"
//#include "MainPanel.h"
#include "ZTconfigmgr.h"
#include <QApplication>
#include "EngLog.h"
#include <QDebug>

#include "Angrignon.h"
#include "BerriUQAM.h"
#include "CoteVertu.h"
#include "HenriBourassa.h"
#include "HonoreBeaugrand.h"
#include "Longueuil.h"
#include "Montmorency.h"
#include "Montmorency1012.h"
#include "Montmorency1022.h"
#include "SaintMichel.h"
#include "Snowdon.h"
#include "DuCollege.h"
#include "SimulatorIOManager.h"
#include "SimulatorLazerProbesMgr.h"
#include "SimulatorPCIIO.h"
#include <QElapsedTimer>
#include "ZTLog.h"
#include "RamMonitor.h"
#include "PCI1756Interface.h"
#include "USB4704Interface.h"
#include "ZTVersion.h"
#include "ModbusCCDefs.h"
#include "ModbusTKTransport.h"
#include "ModbusSEIDefs.h"
#include <sys/time.h>
#include "PIHistorianDefs.h"





#ifdef USE_NETWORKING
#include "NetworkManager.h"
#endif

#include "qextserialport.h"

CZoneTest::CZoneTest():
    mZTStation(0),
    mZtState(ZT_INIT_STATE)
{
    mZTStartDateTime = QDateTime::currentDateTime();

    mZTStateMachineTimer = new QTimer();
    connect(mZTStateMachineTimer, SIGNAL(timeout()), this, SLOT(SMTimerExpired()));
	panel.installEventFilter(this);	//Install an event filter for CZoneTest to manage some events from GUI

    mZTStateMachine = new CZTStateMachine(this);
	mZTSimulator = 0;
	mIOManager = 0;
	mLazerProbesManager = 0;
    mAnalogModule = 0;
    mTKTransportInterface = 0;
    mCCModbusRepository = 0;
    mModbusCCMgr = 0;
    mModbusSEIMgr = 0;

    mSimulationON = false;
    mWatchdogEnabled = true;
    mZTSettings = new CZTSettingsData();

	mEventMgr = new CEventMgr();
	mLogMgr = new CLogMgr();
	mUSBDriveInterface = new CUSBDriveInterface();

	mExtIOWorkerThread = new CExtIOThread;
	mExtIOThread = new QThread;
	mExtIOWorkerThread->moveToThread(mExtIOThread);
	connect(mExtIOThread,SIGNAL(started()),mExtIOWorkerThread,SLOT(DoAcquisition()));

    mPIHistorianManager = 0;

}
CZoneTest::~CZoneTest()
{
    delete mLogMgr;
    delete mEventMgr;
	delete mUSBDriveInterface;
	delete mLazerProbesManager;
	delete mZTStateMachine;
	delete mIOManager;
    delete mPCIIO;
    delete mZTStation;
    delete mZTSettings;
	delete mExtIOThread;
	delete mExtIOWorkerThread;
    delete mInternalWatchdog;

    if(mTKTransportInterface != 0)
        delete mTKTransportInterface;

    if(mCCModbusRepository != 0)
        delete mCCModbusRepository;

    if(mModbusCCMgr != 0)
    {
        delete mModbusCCMgr;
    }

    if(mModbusSEIMgr != 0)
    {
        delete mModbusSEIMgr;
    }

	if(mAnalogModule != 0)
		delete mAnalogModule;

    if(mPIHistorianManager != 0)
        delete mPIHistorianManager;
}

unsigned int CZoneTest::ExecStateMachine(eZTSMEvents_t)
{
	switch(mZtState)
	{
		case ZT_INIT_STATE:
		{
            mZTStateMachineTimer->stop();
            mZtState = ZT_RUN_STATE;
            mWatchdogTimer.start();
            mZTStateMachineTimer->setSingleShot(false);

            int ret = InitZT();

            mInternalWatchdog->StartWatchdog();

            if(ret == RET_OK)
            {
                mZTStateMachineTimer->start(0);
                mExtIOWorkerThread->SetOutputFlags(mZTStation->GetOutputMasks()->OutputWatchdogMask);
                mWatchdogTimer.start();
            }
			break;
		}
		case ZT_RUN_STATE:
		{
            static bool sExtWatchdogFlag = true;
			mZTStateMachine->ZTStateMachine(ZT_TICK_EVENT);
            mInternalWatchdog->KickWatchdog();
            if(mWatchdogEnabled)
            {
                if(sExtWatchdogFlag == true)
                {
                    if(mWatchdogTimer.elapsed() >= ZT_EXTERNAL_WATCHDOG_PULSE_TIME)
                    {
                        mExtIOWorkerThread->ClearOutputFlags(mZTStation->GetOutputMasks()->OutputWatchdogMask);
                        mWatchdogTimer.start();
                        sExtWatchdogFlag = false;
                    }
                }
                else
                {
                    if(mWatchdogTimer.elapsed() >= ZT_EXTERNAL_WATCHDOG_TIMEOUT)
                    {
                        mExtIOWorkerThread->SetOutputFlags(mZTStation->GetOutputMasks()->OutputWatchdogMask);
                        mWatchdogTimer.start();
                        sExtWatchdogFlag = true;
                    }
                }
            }
			break;
		}
		case ZT_DEADLOCK_STATE:
		{
			//Stay in this state after a fatal error happened.
            mInternalWatchdog->KickWatchdog();
            if(mWatchdogEnabled)
            {
                if(mWatchdogTimer.elapsed() >= ZT_EXTERNAL_WATCHDOG_TIMEOUT)
                {
                    mExtIOWorkerThread->ToggleOutputFlags(mZTStation->GetOutputMasks()->OutputWatchdogMask);
                    mWatchdogTimer.start();
                }
            }

			break;
		}
		case ZT_EXIT_APPLICATION_STATE:
		{
			mZTStateMachineTimer->stop();
            mInternalWatchdog->StopWatchdog();

			QApplication::exit(78);	//Quit the application
			break;
		}
        case ZT_POWER_BUTTON_EXIT_STATE:
        {
            mZTStateMachineTimer->stop();
            mInternalWatchdog->StopWatchdog();

            //Initiate a system shutdown            
            system("shutdown -h -P now");

            QApplication::exit(79);	//Quit the application
            break;
        }
        case ZT_SYSTEM_REBOOT_EXIT_STATE:
        {
            //Initiate a system reboot
            mZTStateMachineTimer->stop();
            mInternalWatchdog->StopWatchdog();

            //Initiate a system reboot
            system("shutdown -r now");
            //system("reboot");     //Not working well all the times



            QApplication::exit(80); //Quit the application
            break;
        }
		default:
		{
		}

	}
	return RET_OK;
}

void CZoneTest::SMTimerExpired()
{
    ExecStateMachine(ZT_SM_TICK_EVENT);
}

unsigned int CZoneTest::Start()
{

    //init some pointers...
    mWelcomePagePtr = panel.mWelcomePage;
	panel.mProgramHandle = this;
	panel.mZTMainPage->mProgramHandle = this;
	panel.mOptionsPage->mProgramHandle = this;
	panel.mFunctionSelectPage->mProgramHandle = this;
//    panel.mFunctionSelectPage->SetConfig(mZTSettings->mDetectionFunctionSettings);
	panel.mZTMainPage->SetEventListPtr(&mEventMgr->mEventsList);
	panel.mLogsListPage->mProgramHandle = this;
	panel.mLogsListPage->mLogMgrHandle = mLogMgr;
    panel.mLogViewPage->mProgramHandle = this;
    panel.mMaintenancePage->mProgramHandle = this;
	panel.mGeneralSettingsPage->mProgramHandle = this;
    panel.mModbusSettingsPage->mProgramHandle = this;
    panel.mSEISettingsPage->mProgramHandle = this;
	panel.mZTLogViewerPage->mProgramHandle = this;
    panel.mModbusDisplayPage->mProgramHandle = this;
    panel.mHistorienDisplayPage->mProgramHandle = this;
	panel.mEngineeringPage->mDisablePassword = mDisablePassword;
    mInternalWatchdog = new CWatchdogCtrl(mUseWatchdog);





#ifdef USE_NETWORKING
    CNetworkManager::instance()->BindPointers(this);
#endif

	mEventMgr->mProgramPTr = this;
	mEventMgr->mMainPagePtr = panel.mZTMainPage;
//    mEventMgr->UpdateEvents(mZTSettings->mDetectionFunctionSettings);

    mZTStateMachine->mZTDetectionConfig = mZTSettings->mDetectionFunctionSettings;
    connect(mZTStateMachine,SIGNAL(NewTrainLogSaved(QString,bool)),panel.mLogsListPage,SLOT(NewTrainLogFileSaved(QString,bool)));

   // connect(mZTStateMachine,SIGNAL(NewTrainLogSaved(QString,bool)),&mNetworkDriveMgr,SLOT(NewTrainFileSaved(QString,bool)));  //JFM déplacé plus bas, connect seulement si NetworkDrive est activé

    CZTLog::instance()->mProgramHandle = this;



    //Show Graphic User Interface.
	panel.setWindowTitle("ZoneTest");
	if(mFullScreen)
	{
		panel.showFullScreen();
	}
	else
	{
		panel.show();
	}

    mWelcomePagePtr->ClearTextBoxWidget();
    mWelcomePagePtr->InsertTextBoxString("Application Zone Tests");
    mWelcomePagePtr->InsertTextBoxString(QString().sprintf("Version: %s",ZT_SOFT_VERSION));
    mWelcomePagePtr->ShowTextboxWidget();

	mZTStateMachineTimer->setSingleShot(false);
    mZTStateMachineTimer->start(1000);
    return RET_OK;
}


unsigned int CZoneTest::InitZT()
{

    //mWelcomePagePtr->ClearTextBoxWidget();

	CheckAndCreateDirectories();

    CZTLog::instance()->Init();

        //Load the config file
    if(CZTConfigMgr::instance()->LoadZTConfig() != ZT_CONFIG_OK)
    {
        mWelcomePagePtr->InsertTextBoxString("Erreur d'ouverture du fichier de configuration");
        mWelcomePagePtr->InsertTextBoxString("Vérifier la présence du fichier ZT.conf");
	//    mWelcomePagePtr->InsertTextBoxString("L'exécution du logiciel va se terminer.");

		EnterDeadlockState();
        return RET_ERROR;
    }



    //Create engineering log if defined in config file.
    if(CZTConfigMgr::instance()->GetEngLog() != -1)
    {
        CEngLog::instance()->Init(CZTConfigMgr::instance()->GetEngLog());
    }
    else
        qDebug("Engineering Log disabled");


    //Load the ZoneTest settings
    mZTSettingsFileMgr.LoadSettings(mZTSettings);
    mEventMgr->UpdateEvents(mZTSettings->mDetectionFunctionSettings);
    panel.mFunctionSelectPage->SetConfig(mZTSettings->mDetectionFunctionSettings);
    mLogMgr->SetMaxLogFilesCount(mZTSettings->mMaxLogCount);
    mLogMgr->KeepAllMPM10Logs(mZTSettings->mKeepMPM10Logs);
    mLogMgr->KeepAllZT1Logs(mZTSettings->mKeepAllZT1Logs);
    mLogMgr->KeepAllZT2Logs(mZTSettings->mKeepAllZT2Logs);
    panel.mEngineeringPage->ZTLogFilesSettings(mZTSettings->mMaxLogCount,mZTSettings->mKeepMPM10Logs,mZTSettings->mKeepAllZT1Logs,mZTSettings->mKeepAllZT2Logs);

    connect(&mACPISocket,SIGNAL(connected()),this,SLOT(ACPISocketConnected()));
    connect(&mACPISocket,SIGNAL(readyRead()),this,SLOT(ACPISocketEvent()));
    mACPISocket.connectToServer("/var/run/acpid.socket",QIODevice::ReadOnly);

	//Check if we must enter simulated mode
	if(CZTConfigMgr::instance()->GetSimulatorEnabled() == true)
	{
		mSimulationON = true;
		CZTLog::instance()->AddLogString("Mode Simulation détecté.",true);

		//Create simulated I/O objects
		mIOManager = new CSimulatorIOManager();
		mLazerProbesManager = new CSimulatorLazerProbesMgr();
		mPCIIO = new CSimulatorPCIIO();

        mZTSimulator = new CZTSimulator((CSimulatorIOManager*)mIOManager);
//		mZTSimulator->Init(panel.mZTMainPage);
		panel.mZTMainPage->SetZTSimulator(mZTSimulator);

		mZTSimulator->SetPGTreshold(mZTSettings->mPGTreshold);
	}
	else
	{
#ifndef WINDOWS_OS
		//Create actual I/O objects
		mIOManager = new CExternalIOMgr();
		if(mSimulateLazerProbes)
		{
			mLazerProbesManager = new CSimulatorLazerProbesMgr();
		}
		else
		{
			mLazerProbesManager = new CLazerProbesMgr();
		}
	#ifdef USE_DAQNAVI_LIB
		mPCIIO = new CPCI1756Interface();
	#else
			mPCIIO = new CComediLibInterface();
	#endif
#endif
	}


	//Open the external IO modules connection and create instances of
    //the modules as they are configured in the config file.
	if(mIOManager->InitIO() != EXTIO_MGR_RET_OK)
    {

        mWelcomePagePtr->InsertTextBoxString(QString("Impossible d'initialiser les modules externes"));
        mWelcomePagePtr->InsertTextBoxString(QString("Vérifier le fichier de configuration et la connexion au module maître."));
		CZTLog::instance()->AddLogString("Impossible d'initialiser les modules externes",true);

        mWatchdogEnabled=false;
		EnterDeadlockState();
        return RET_ERROR;
    }
	mWelcomePagePtr->InsertTextBoxString(QString("Initialisation des modules externes: OK"));

	mAnalogModule = 0;


	//Open advantech USB-4704 analog acquisition module.
	CUSB4704Interface *USBAnalogModule = new CUSB4704Interface();
	if(USBAnalogModule->OpenInterface() == RET_OK)
	{
		mAnalogModule = USBAnalogModule;
	}


#ifndef NO_PCI_CARD_INSTALLED
    //Open an check internal PCI inputs/outputs adapter card.
	if(mPCIIO->OpenPCIInterface() != PCIIO_OK)
    {
        mWelcomePagePtr->InsertTextBoxString(QString("Impossible d'initialiser la carte PCI"));
		CZTLog::instance()->AddLogString(QString("Impossible d'initialiser la carte PCI"),true);

		EnterDeadlockState();
		return RET_ERROR;
    }
	mWelcomePagePtr->InsertTextBoxString(QString("Initialisation de la carte PCI: OK"));
#else
    mWelcomePagePtr->InsertTextBoxString(QString("Carte PCI Ignorée. (NO_PCI_CARD_INSTALLED)"));
#endif

	//Open the lazer probes as configured in the config file
	if(mLazerProbesManager->InitLazerProbes() != LAZERPROBES_MGR_RET_OK)
	{
		mWelcomePagePtr->InsertTextBoxString(QString("Impossible d'initialiser une ou plusieurs sondes laser"));

		CZTLog::instance()->AddLogString(QString("Impossible d'initialiser une ou plusieurs sondes laser"),true);
		EnterDeadlockState();
		return RET_ERROR;
	}
	mWelcomePagePtr->InsertTextBoxString(QString("Initialisation des sondes laser: OK"));



    //Instantiate the station according to the physical key
    if(InitStation() == RET_ERROR)
    {
		EnterDeadlockState();
        return RET_ERROR;
    }
     mZTSettingsFileMgr.SetStationName(GetStationTextualName());

    mOutputModule = (COutputModule*)mIOManager->GetModule(IO_MODULE_OUTPUT_TYPE,1);

	mExtIOWorkerThread->BindPointers((CInputModule*)mIOManager->GetModule(IO_MODULE_INPUT_TYPE,1),
									 (COutputModule*)mIOManager->GetModule(IO_MODULE_OUTPUT_TYPE,1),
									 (CAnalogInputModule*)mIOManager->GetModule(IO_MODULE_MIXED_TYPE,1),
									 mZTStation->GetAnalogAcqChannels()->SDFAcquisitionChannel);

	mExtIOThread->start(QThread::NormalPriority);

    bool UseModbusInterface = mZTSettings->mUseModbusCC;

    if(UseModbusInterface == true)
    {
        int ModbusCCPort = CZTConfigMgr::instance()->GetModbusCCPort();
        int CCDevID = CZTConfigMgr::instance()->GetModbusCCDevID();
        int ModbusSEIPort = CZTConfigMgr::instance()->GetModbusSEIPort();
        int SEIDevID = CZTConfigMgr::instance()->GetModbusSEIDevID();
        mWatchdogEnabled=false;

        if(CCDevID >= 255)
        {
            mWelcomePagePtr->InsertTextBoxString(QString("Valeur DevID Modbus CC invalide (%1)").arg(CCDevID));
            CEngLog::instance()->AddLogString(QString("Valeur DevID Modbus CC invalide (%1)").arg(CCDevID),1);
            EnterDeadlockState();
            return RET_ERROR;
        }

        if(SEIDevID >= 255)
        {
            mWelcomePagePtr->InsertTextBoxString(QString("Valeur DevID Modbus SEI invalide (%1)").arg(SEIDevID));
            CEngLog::instance()->AddLogString(QString("Valeur DevID Modbus SEI invalide (%1)").arg(SEIDevID),1);
            EnterDeadlockState();
            return RET_ERROR;
        }

        mCCModbusRepository = new CModbusRepository;
        mCCModbusRepository->AddHRDataMap(MODBUS_ZT_DATA_BASE_REG,MODBUS_ZT_TABLE_DATA_SIZE);    //Add the ZT data map
        mCCModbusRepository->AddHRDataMap(MODBUS_CC_DATA_BASE_REG_ADD,MODBUS_ZT_TABLE_DATA_SIZE);    //Add the CC data map
        if(mModbusCCMgr == 0)
        {
            mModbusCCMgr = new CModbusCCMgr(mCCModbusRepository,ModbusCCPort,CCDevID);
        }
        mModbusCCMgr->StartModbusCCServer();


        mSEIModbusRepository = new CModbusRepository;
        mSEIModbusRepository->AddHRDataMap(SEI_MODBUS_ZT_DATA_BASE_REG,SEI_MODBUS_ZT_TABLE_DATA_SIZE);  //Add the ZT data map
        mSEIModbusRepository->AddHRDataMap(SEI_MODBUS_SEI_DATA_BASE_REG,SEI_MODBUS_SEI_TABLE_DATA_SIZE); //Add the SEI data map
        if(mModbusSEIMgr == 0)
        {
            mModbusSEIMgr = new CModbusSEIMgr(mSEIModbusRepository,mCCModbusRepository,mZTSettings->mSEIModbusHostAddress,ModbusSEIPort,SEIDevID);
        }
        mModbusSEIMgr->StartSEICommunication();

        connect(mModbusSEIMgr,SIGNAL(ModbusMasterConnected(qint32,qint32)),panel.mSEISettingsPage,SLOT(ModbusSEIConnected(qint32,qint32)));
        connect(mModbusSEIMgr,SIGNAL(ModbusMasterDisconnected()),panel.mSEISettingsPage,SLOT(ModbusSEIDisconnected()));
        connect(mModbusSEIMgr,SIGNAL(SEIModbusLinkLost()),panel.mSEISettingsPage,SLOT(ModbusSEILinkDown()));
        connect(mModbusSEIMgr,SIGNAL(SEIModbusLinkRecovered()),panel.mSEISettingsPage,SLOT(ModbusSEILinkUP()));
        connect(mModbusSEIMgr,SIGNAL(SEIModbusLinkRecovered()),panel.mZTMainPage,SLOT(ModbusSEIConnected()));
        connect(mModbusSEIMgr,SIGNAL(SEIModbusLinkLost()),panel.mZTMainPage,SLOT(ModbusSEIDisconnected()));

        panel.mModbusDisplayPage->mSEIRepoHandle = mSEIModbusRepository;
        panel.mModbusDisplayPage->mCCRepoHandle = mCCModbusRepository;


        panel.mZTMainPage->ModbusSEIDisconnected();


        CModbusTKTransport *TransportInterface = new CModbusTKTransport(mCCModbusRepository,mSEIModbusRepository);
        mTKTransportInterface = (CTKTransportInterface*)TransportInterface;
        connect(mModbusCCMgr,SIGNAL(RepoHasChanged()),TransportInterface,SLOT(ModbusCCUpdated()));
        connect(mModbusSEIMgr,SIGNAL(SEIAlarmClearUpdate(bool,bool)),TransportInterface,SLOT(ModbusSEIClearUpdate(bool,bool)));

        mZTStateMachine->BindModbusCCMgrPtr(mModbusCCMgr);
        connect(mModbusCCMgr,SIGNAL(ModbusCCLinkRecovered()),panel.mZTMainPage,SLOT(ModbusCCConnected()));
        connect(mModbusCCMgr,SIGNAL(ModbusCCLinkLost()),panel.mZTMainPage,SLOT(ModbusCCDisconnected()));
        connect(mModbusCCMgr,SIGNAL(ModbusDateTimeReceived(QDateTime*)),this,SLOT(ModbusDateTimeUpdate(QDateTime*)));
        connect(mModbusCCMgr,SIGNAL(ModbusCCConnected(qint32,qint32)),panel.mModbusSettingsPage,SLOT(ModbusCCConnected(qint32,qint32)));
        connect(mModbusCCMgr,SIGNAL(ModbusCCDisconnected()),panel.mModbusSettingsPage,SLOT(ModbusCCDisconnected()));
        connect(mModbusCCMgr,SIGNAL(ModbusCCLinkLost()),panel.mModbusSettingsPage,SLOT(ModbusCCLinkDown()));
        connect(mModbusCCMgr,SIGNAL(ModbusCCLinkRecovered()),panel.mModbusSettingsPage,SLOT(ModbusCCLinkUP()));

        connect(TransportInterface,SIGNAL(TKUpdated()),mModbusSEIMgr,SLOT(ZTTKUpdated()));

        panel.mZTMainPage->ModbusCCDisconnected();
        panel.mZTMainPage->mZT1Stats->Init(true);
        panel.mZTMainPage->mZT2Stats->Init(true);


        bool UseNetworkDrive = CZTConfigMgr::instance()->GetSAMBADriveActivated();
        QString SAMBAMountPoint = CZTConfigMgr::instance()->GetSAMBAMountPoint();
        QString SAMBALogin = CZTConfigMgr::instance()->GetSAMBALogin();
        QString SAMBAPassword = CZTConfigMgr::instance()->GetSAMBAPassword();
        QString SAMBADomain = CZTConfigMgr::instance()->GetSAMBADomain();
        mNetworkDriveMgr.InitNetDriveMgr(UseNetworkDrive,SAMBAMountPoint,SAMBALogin,SAMBAPassword,SAMBADomain,mZTStation->GetStationShortName());
        if(UseNetworkDrive == true)
        {
            connect(mZTStateMachine,SIGNAL(NewTrainLogSaved(QString,bool)),&mNetworkDriveMgr,SLOT(NewTrainFileSaved(QString,bool)));
        }

    }
    else
    {
        CDiscreteTKTransport *TransportInterface = new CDiscreteTKTransport;
        mTKTransportInterface = (CTKTransportInterface*)TransportInterface;
        TransportInterface->BindPointers(mZTStation->GetOutputMasks(),mExtIOWorkerThread);
        panel.mZTMainPage->mZT1Stats->Init(false);
        panel.mZTMainPage->mZT2Stats->Init(false);
        mNetworkDriveMgr.InitNetDriveMgr(false,"","","","","");
    }
    connect(mTKTransportInterface,SIGNAL(TKOutputStatesChanged(bool,bool)),panel.mMaintenancePage,SLOT(TKOutputChanged(bool,bool)));

    //Start SFTP file copy service
    bool EnableSFTPClient = CZTConfigMgr::instance()->GetSFTPActivated();
    QString SFTPLogin = CZTConfigMgr::instance()->GetSFTPLogin();
    QString SFTPPassword = CZTConfigMgr::instance()->GetSFTPPassword();
    QString SFTPServerAddress = CZTConfigMgr::instance()->GetSFTPServerAddress();
    QString SFTPRemoteDir = CZTConfigMgr::instance()->GetSFTPServerRemoteDir();
    bool UseEngLog = CZTConfigMgr::instance()->GetEngLog() != -1;
    mSFTPManager.InitFTPServerManager(EnableSFTPClient,SFTPLogin,SFTPPassword,SFTPServerAddress,SFTPRemoteDir,mZTStation->GetStationShortName(),UseEngLog);
    if(EnableSFTPClient == true)
    {
        connect(mZTStateMachine,SIGNAL(NewTrainLogSaved(QString,bool)),&mSFTPManager,SLOT(NewTrainFileSaved(QString,bool)));
    }

    //Start Historien PI server
    bool EnableHistorian = CZTConfigMgr::instance()->GetPIHistorianEnabled();
    int PIHistorianPort = CZTConfigMgr::instance()->GetPIHistorianModbusPort();
    int PIHistorianDevID = CZTConfigMgr::instance()->GetPIHistorianModbusDevID();
    if(EnableHistorian == true)
    {
        mPIHistorianRepository = new CModbusRepository;
        mPIHistorianRepository->AddHRDataMap(HISTORIAN_ZT_DATA_BASE_REG,HISTORIAN_MODBUS_ZT_TABLE_DATA_SIZE);    //Add the ZT data map
        mPIHistorianManager = new CPIHistorianManager(mPIHistorianRepository,PIHistorianPort,PIHistorianDevID);

        panel.mHistorienDisplayPage->mHistorienRepoHandle = mPIHistorianRepository;


        if(UseModbusInterface)
        {
            connect(mModbusCCMgr,SIGNAL(ModbusCCConnected(qint32,qint32)),mPIHistorianManager,SLOT(HPCConnected(qint32,qint32)));
            connect(mModbusCCMgr,SIGNAL(ModbusCCDisconnected()),mPIHistorianManager,SLOT(HPCDisconnected()));
            connect(mModbusSEIMgr,SIGNAL(ModbusMasterConnected(qint32,qint32)),mPIHistorianManager,SLOT(SEIConnected(qint32,qint32)));
            connect(mModbusSEIMgr,SIGNAL(ModbusMasterDisconnected()),mPIHistorianManager,SLOT(SEIDisconnected()));
        }
        connect(mPIHistorianManager,SIGNAL(HistorianConnected()),panel.mZTMainPage,SLOT(ModbusHistorienConnected()));
        connect(mPIHistorianManager,SIGNAL(HistorianDisconnected()),panel.mZTMainPage,SLOT(ModbusHistorienDisconnected()));
        panel.mZTMainPage->ModbusHistorienDisconnected();

        mPIHistorianManager->UpdateDetectionFunctions(mZTSettings->mDetectionFunctionSettings);
        mPIHistorianManager->UpdatePGTreshold(mZTSettings->mPGTreshold);
        mPIHistorianManager->UpdateMaintenanceMode(false);
        mPIHistorianManager->SetSystemStartDateTime(mZTStartDateTime);

        mPIHistorianManager->StartPIHistorian();

    }

	if(mSimulationON == true)
	{
#ifdef USE_REAL_ANALOG_EXTERNAL_MODULE
		mZTSimulator->Init(panel.mZTMainPage,mZTStation,mIOManager,mPCIIO,mLazerProbesManager,mUSBDriveInterface,mAnalogModule);
#else
		mZTSimulator->Init(panel.mZTMainPage,mZTStation,mIOManager,mPCIIO,mLazerProbesManager,mUSBDriveInterface);
#endif
		mZTStateMachine->BindPointers(mZTStation,
									  mExtIOWorkerThread,
									  mExtIOWorkerThread,
									  panel.mZTMainPage,
									  mPCIIO,
									  mLazerProbesManager->GetLazerProbeHandle(LAZER_PROBE_TYPE_INTERNAL,1),
									  mLazerProbesManager->GetLazerProbeHandle(LAZER_PROBE_TYPE_EXTERNAL,1),
									  mLogMgr,
                                      mTKTransportInterface,
									  mZTSimulator,
									  mAnalogModule);

	}
	else
	{
		mZTStateMachine->BindPointers(mZTStation,
									  mExtIOWorkerThread,
									  mExtIOWorkerThread,
									  panel.mZTMainPage,
									  mPCIIO,
									  mLazerProbesManager->GetLazerProbeHandle(LAZER_PROBE_TYPE_INTERNAL,1),
									  mLazerProbesManager->GetLazerProbeHandle(LAZER_PROBE_TYPE_EXTERNAL,1),
									  mLogMgr,
                                      mTKTransportInterface,
									  0,
									  mAnalogModule);
	}

	mZTStateMachine->SetPGTreshold(mZTSettings->mPGTreshold);
	panel.mEngineeringPage->BindPointers(this,
											 mExtIOWorkerThread,
											 mExtIOWorkerThread,
											 mPCIIO,
											 mZTSettings,
											 mUSBDriveInterface,
											 mZTStation,
											 mAnalogModule);
	connect(mZTStateMachine,SIGNAL(PGCalibrationFinished(int)),panel.mEngineeringPage,SLOT(PGCalibFinished(int)));
	connect(mZTStateMachine,SIGNAL(PGCalibrationStatus(int,int)),panel.mEngineeringPage,SLOT(PGCalibUpdate(int,int)));
	connect(mZTStateMachine,SIGNAL(MaintenancePPActivated(uint)),panel.mMaintenancePage,SLOT(PPActivated(uint)));
	panel.mEngineeringPage->Init();
	if(mSimulationON == false)
	{
		connect((CLazerProbe*)mLazerProbesManager->GetLazerProbeHandle(LAZER_PROBE_TYPE_INTERNAL,1),SIGNAL(NewProbeData(unsigned int,unsigned int)),panel.mEngineeringPage,SLOT(LazerProbeDataAvailable(uint,uint)));
		connect((CLazerProbe*)mLazerProbesManager->GetLazerProbeHandle(LAZER_PROBE_TYPE_EXTERNAL,1),SIGNAL(NewProbeData(unsigned int,unsigned int)),panel.mEngineeringPage,SLOT(LazerProbeDataAvailable(uint,uint)));
	}
	else
	{
		connect((CSimulatorLazerProbe*)mLazerProbesManager->GetLazerProbeHandle(LAZER_PROBE_TYPE_INTERNAL,1),SIGNAL(NewProbeData(unsigned int,unsigned int)),panel.mEngineeringPage,SLOT(LazerProbeDataAvailable(uint,uint)));
		connect((CSimulatorLazerProbe*)mLazerProbesManager->GetLazerProbeHandle(LAZER_PROBE_TYPE_EXTERNAL,1),SIGNAL(NewProbeData(unsigned int,unsigned int)),panel.mEngineeringPage,SLOT(LazerProbeDataAvailable(uint,uint)));

	}

    panel.mZTMainPage->SetZT2Presence(mZTStation->StationHasZT2());
    mZTStateMachine->SetZT2Presence(mZTStation->StationHasZT2());
    mWelcomePagePtr->InsertTextBoxString(QString("Chargement des fichiers de passage de trains..."));
	mLogMgr->ParseLogs();
    mWelcomePagePtr->InsertTextBoxString(QString("Chargement des fichiers de passage de trains: OK"));
    mZTStateMachine->SetAutoExportZT1CSV(mZTSettings->mAutoExportZT1CSV);
    mZTStateMachine->SetAutoExportZT2CSV(mZTSettings->mAutoExportZT2CSV);
    panel.mGeneralSettingsPage->UseNetworkTime(mZTSettings->mUseNetworkTime,true);
	panel.mLogsListPage->BindPointers(mUSBDriveInterface);
	mUSBDriveInterface->Start();
//    if(mDI710Module != 0)
//       mDI710Module->StartAcquisition();

#ifdef USE_NETWORKING
        CNetworkManager::instance()->StartServer();
#endif

	//CRamMonitor::instance()->StartTimer();


	CEngLog::instance()->AddLogString("Initialisation de la Zone Test réussie");
	panel.HideWelcomePage();
	panel.ShowMainPage();

	return RET_OK;
}

unsigned int CZoneTest::Run()
{
    return RET_OK;
}

unsigned int CZoneTest::InitStation()
{
    CEngLog::instance()->AddLogString("CZoneTest::InitStation.  Initialisation de la station");
    QString StationName = CZTConfigMgr::instance()->GetStationName();

    if(mSimulationON == false && mIgnoreStationPhysicalKey == false)	//Do not check station physical key in sim mode or if IgnoreKey switch activated.
    {
        CInputModule *inputmodule = (CInputModule*)mIOManager->GetModule(IO_MODULE_INPUT_TYPE,1);	//Access the module directly since the thread is not yet started...

        unsigned int key = inputmodule->GetInputs();

        if((key & ANGRIGNON_IN_STATION_ID_MASK) == ANGRIGNON_STATION_KEY)
        {
            StationName = "ANGRIGNON";
        }
        else if((key & BERRIUQAM_IN_STATION_ID_MASK) == BERRIUQAM_STATION_KEY)
        {
            StationName = "BERRI_UQAM";
        }
        else if((key & COTEVERTU_IN_STATION_ID_MASK) == COTEVERTU_STATION_KEY)
        {
            StationName = "COTE_VERTU";
        }
        else if((key & HENRIBOURASSA_IN_STATION_ID_MASK) == HENRIBOURASSA_STATION_KEY)
        {
            StationName = "HENRI_BOURASSA";
        }
        else if((key & HONOREBEAUGRAND_IN_STATION_ID_MASK) == HONOREBEAUGRAND_STATION_KEY)
        {
            StationName = "HONORE_BEAUGRAND";
        }
        else if((key & LONGUEUIL_IN_STATION_ID_MASK) == LONGUEUIL_STATION_KEY)
        {
            StationName = "LONGUEIL";
        }
        else if((key & MONTMORENCY_IN_STATION_ID_MASK) == MONTMORENCY_STATION_KEY)
        {
            StationName = "MONTMORENCY";
        }
//        else if((key & MONTMORENCY1012_IN_STATION_ID_MASK) == MONTMORENCY1012_STATION_KEY)
//        {
//            StationName = "MONTMORENCY_10_12";
//        }
        else if((key & MONTMORENCY1022_IN_STATION_ID_MASK) == MONTMORENCY1022_STATION_KEY)
        {
            StationName = "MONTMORENCY_10_22";
        }
        else if((key & SAINTMICHEL_IN_STATION_ID_MASK) == SAINTMICHEL_STATION_KEY)
        {
            StationName = "SAINT_MICHEL";
        }
        else if((key & SNOWDON_IN_STATION_ID_MASK) == SNOWDON_STATION_KEY)
        {
            StationName = "SNOWDON_L5";
        }
        else if((key & DUCOLLEGE_IN_STATION_ID_MASK) == DUCOLLEGE_STATION_KEY)
        {
            StationName = "DU_COLLEGE";
        }
        else
        {
            CEngLog::instance()->AddLogString(QString("ERREUR.  Clef électrique de station inconnue: ") + StationName,2);
            CEngLog::instance()->AddLogString(QString("Impossible d'initialiser la station"),1);
            mWelcomePagePtr->InsertTextBoxString("Erreur:  Station non reconnue");
            mWelcomePagePtr->InsertTextBoxString("Vérifier la clef électrique");
            return RET_ERROR;
        }
    }

    if(StationName == "HONORE_BEAUGRAND")
    {
        mZTStation = new CHonoreBeaugrandStation();
    }
    else if(StationName == "ANGRIGNON")
    {
        mZTStation = new CAngrignonStation();
    }
    else if(StationName == "HENRI_BOURASSA")
    {
        mZTStation = new CHenriBourassaStation();
    }
    else if(StationName == "COTE_VERTU")
    {
        mZTStation = new CCoteVertuStation();
    }
    else if(StationName == "BERRI_UQAM")
    {
        mZTStation = new CBerriUQAMStation();
    }
    else if(StationName == "LONGUEIL")
    {
        mZTStation = new CLongueuilStation();
    }
    else if(StationName == "SAINT_MICHEL")
    {
        mZTStation = new  CSaintMichelStation();
    }
    else if(StationName == "SNOWDON_L5")
    {
        mZTStation = new CSnowdonStation();
    }
	else if(StationName == "MONTMORENCY")
    {
        mZTStation = new CMontmorencyStation();
    }
    else if(StationName == "MONTMORENCY_10_12")
    {
        mZTStation = new CMontmorency1012Station();
    }
    else if(StationName == "MONTMORENCY_10_22")
    {
        mZTStation = new CMontmorency1022Station();
    }
    else if(StationName == "DU_COLLEGE")
    {
        mZTStation = new CDuCollegeStation();
    }

    else
    {
        CEngLog::instance()->AddLogString(QString("ERREUR.  Nom de station invalide : ") + StationName,2);
        CEngLog::instance()->AddLogString(QString("Impossible d'initialiser la station"),1);
        mWelcomePagePtr->InsertTextBoxString("Erreur.  Vérifier le fichier de configuration");
        mWelcomePagePtr->InsertTextBoxString(QString("Nom de station invalide : ") + StationName);
        return RET_ERROR;
    }

//	mZTStation->InitStation(mIOManager,mLazerProbesManager);



	mZTStation->BuildCDVList();
	panel.mZTMainPage->SetStationName(mZTStation->GetStationTextualName());
	panel.mZTMainPage->SetCDVList(mZTStation->GetCDVList());
    CZTLog::instance()->AddLogString(QString("Station initialisée : ") + mZTStation->GetStationTextualName(),true);
	mWelcomePagePtr->InsertTextBoxString(QString("Station initialisée : ") + mZTStation->GetStationTextualName());




    return RET_OK;

}

void CZoneTest::EnterDeadlockState()
{
	//TODO: Set flags, Alarms, etc..

	CZTLog::instance()->AddLogString(QString("L'exécution de l'application est terminée.  DEADLOCK"),true);

	mZtState = ZT_DEADLOCK_STATE;
}

//Catch and manage some events from the graphics user interface
//like the keyboard Exit sequence (Ctrl-F10)
bool CZoneTest::eventFilter(QObject *obj, QEvent *event)
{
	if(obj == &panel) //Check if event is coming from the GUI
	{
		if(event->type() == QEvent::KeyPress)
		{
			QKeyEvent *KeyEvent = static_cast<QKeyEvent*>(event);

			//Check if we received CTRL-F10
			if(KeyEvent->key() == Qt::Key_F10 &&
			   KeyEvent->modifiers() == Qt::ControlModifier)
			{
				CZTLog::instance()->AddLogString("CTRL-F10...",true);
				if(mDisablePassword == true)
				{
					CZTLog::instance()->AddLogString("Mot de passe désactivé.  Sortie du programme.",true);

                    ApplicationQuit(EXIT_REASON_USER_REQUEST);
				}
				else
				{
					CZTLog::instance()->AddLogString("Demande du mot de passe.",true);
					panel.mZTMainPage->RequestExitPassword();
				}
				return true;	//keep the keystroke
			}
            else if(KeyEvent->key() == Qt::Key_F4)  //F4 Key toggles the Modbus data display page
            {
                if(mZTSettings->mUseModbusCC == true)
                {
                    if(panel.mModbusDisplayPage->isVisible())
                    {
                        panel.mModbusDisplayPage->hide();
                    }
                    else
                    {
                        panel.mModbusDisplayPage->show();
                    }
                }
            }
            else if(KeyEvent->key() == Qt::Key_F3)  //F3 Key toggles the Historien data display page
            {
                if(CZTConfigMgr::instance()->GetPIHistorianEnabled())
                {
                    if(panel.mHistorienDisplayPage->isVisible())
                    {
                        panel.mHistorienDisplayPage->HideHistorienPage();
                    }
                    else
                    {
                        panel.mHistorienDisplayPage->show();
                    }

                }

            }
		}
	}

	return QObject::eventFilter(obj,event);

}

////Messages from Options page
void CZoneTest::ZTFunctionsOptionSelected()
{
	panel.mOptionsPage->hide();
	panel.mFunctionSelectPage->show();
}

void CZoneTest::ZTMaintenanceOptionSeleced()
{
	panel.mOptionsPage->hide();
    panel.mMaintenancePage->show();
    if(mModbusCCMgr != 0)
    {
        mModbusCCMgr->SetActivatedITI(mZTStation->GetCurrentITI()); //Fetch and update the activated ITI for alarm simulation
    }
}

///////////////

////Messages from Main ZT Page
void CZoneTest::OptionsMenuPageSelected()
{
	panel.mOptionsPage->show();
}

void CZoneTest::LogsPageSelected()
{
	panel.mLogsListPage->RefreshList();
	panel.mLogsListPage->show();
}

void CZoneTest::ProgramExitRequest()
{
    CZTLog::instance()->AddLogString("Mot de passe valide.  Fin du programme.",true);
    ApplicationQuit(EXIT_REASON_USER_REQUEST);
    QApplication::exit(79);
}

/////////////////

////Messages from Detection Functions select page
unsigned int CZoneTest::DetectionFunctionsConfigChanged(CZTDetectionFunctionConfig *NewConfig)
{
    *mZTSettings->mDetectionFunctionSettings = *NewConfig;
    mZTSettingsFileMgr.SaveSettings(mZTSettings);
    mEventMgr->UpdateEvents(mZTSettings->mDetectionFunctionSettings);

    if(mPIHistorianManager != 0)
        mPIHistorianManager->UpdateDetectionFunctions(NewConfig);

	return RET_OK;
}

/////Messages from Logs list page
void CZoneTest::LogViewRequest(CLogElement *element)
{
	panel.mLogsListPage->hide();
    panel.mZTMainPage->hide();

	panel.mLogViewPage->SetLogData(element);
	panel.mLogViewPage->show();

}

QString CZoneTest::GetStationShortName()
{
	return mZTStation->GetStationShortName();
}

QString CZoneTest::GetStationTextualName()
{
	return mZTStation->GetStationTextualName();
}

///  Messages from logs display page
void CZoneTest::LogViewCloseRequest()
{
    panel.mLogViewPage->hide();
    panel.mLogsListPage->show();
    panel.mZTMainPage->show();

}

/// Messages from engineering page
void CZoneTest::OpenEngineeringPageRequest()
{
	panel.mOptionsPage->hide();
	panel.mEngineeringPage->ShowPage();
}

void CZoneTest::CloseEngineeringPageRequest()
{
	panel.mEngineeringPage->hide();
//	panel.mOptionsPage->show();
}

void CZoneTest::SaveAutoExportCSVSettings(bool AutoExportZT1CSV, bool AutoExportZT2CSV)
{
	mZTSettings->mAutoExportZT1CSV = AutoExportZT1CSV;
	mZTSettings->mAutoExportZT2CSV = AutoExportZT2CSV;
	mZTSettingsFileMgr.SaveSettings(mZTSettings);

	mZTStateMachine->SetAutoExportZT1CSV(AutoExportZT1CSV);
	mZTStateMachine->SetAutoExportZT2CSV(AutoExportZT2CSV);
}

void CZoneTest::TrainFilesChanged()
{
	mLogMgr->ParseLogs();
}

bool CZoneTest::StartPGCalibrationRequest(int NbPassages)
{
	if(mZTStateMachine->EnterPGCalibrationMode(NbPassages) == true)
	{
		mEventMgr->AddSingleEvent(EVENT_CA_PG);
		return true;
	}

	return false;
}

bool CZoneTest::StopPGCalibrationRequest()
{
	if(mZTStateMachine->QuitPGCalibrationMode() == true)
	{
		mEventMgr->RemoveSingleEvent(EVENT_CA_PG);
		return true;
	}

	return false;

}

void CZoneTest::HighResLogging(bool HighResON)
{
    mZTStateMachine->SetLogResolution(HighResON);
}

int CZoneTest::GetPGTreshold()
{
	return mZTSettings->mPGTreshold;
}

void CZoneTest::KeepAllMPM10Logs(bool Keep)
{
    mZTSettings->mKeepMPM10Logs = Keep;
    mZTSettingsFileMgr.SaveSettings(mZTSettings);
    mLogMgr->KeepAllMPM10Logs(Keep);
}

void CZoneTest::SetLogFilesNumber(int NbLogFiles)
{
    mZTSettings->mMaxLogCount = NbLogFiles;
    mZTSettingsFileMgr.SaveSettings(mZTSettings);
    mLogMgr->SetMaxLogFilesCount(NbLogFiles);
}

void CZoneTest::KeepAllZT1Logs(bool keep)
{
    mZTSettings->mKeepAllZT1Logs = keep;
    mZTSettingsFileMgr.SaveSettings(mZTSettings);
    mLogMgr->KeepAllZT1Logs(keep);
}
void CZoneTest::KeepAllZT2Logs(bool keep)
{
    mZTSettings->mKeepAllZT2Logs = keep;
    mZTSettingsFileMgr.SaveSettings(mZTSettings);
    mLogMgr->KeepAllZT2Logs(keep);
}


unsigned int CZoneTest::SetPGTreshold(int NewTreshold)
{
	mZTStateMachine->SetPGTreshold(NewTreshold);
	if(mSimulationON)
		mZTSimulator->SetPGTreshold(NewTreshold);
	mZTSettings->mPGTreshold = NewTreshold;
	mZTSettingsFileMgr.SaveSettings(mZTSettings);

    if(mPIHistorianManager != 0)
        mPIHistorianManager->UpdatePGTreshold(NewTreshold);

	return RET_OK;
}

///Messages from Maintenance page
bool CZoneTest::EnterMaintenanceModeRequest()
{
	if(mZTStateMachine->EnterMaintenanceMode() == RET_OK)
	{
		mEventMgr->AddSingleEvent(EVENT_MAINTENANCE);

        if(mPIHistorianManager != 0)
        {
            mPIHistorianManager->UpdateMaintenanceMode(true);
        }
		return true;
	}
	else
		return false;
}

void CZoneTest::ExitMaintenanceModeRequest()
{
    if(mZTSettings->mUseModbusCC == true)
    {
        mModbusCCMgr->SetZTWatchdogEnabled(true);
    }
    else
    {
        mWatchdogEnabled = true;
    }
	mZTStateMachine->QuitMaintenanceMode();
	mEventMgr->RemoveSingleEvent(EVENT_MAINTENANCE);

    if(mPIHistorianManager != 0)
    {
        mPIHistorianManager->UpdateMaintenanceMode(false);
    }
}

unsigned int CZoneTest::ClearMaintenanceCurTKRequest()
{
    return mZTStateMachine->ClearMaintenanceCurrentTK();
}

unsigned int CZoneTest::SendTKToPCC(int DetectionID, int Rank)
{
	return mZTStateMachine->SendTKToPCC(DetectionID,Rank);
}

//THIS IS NOT FOR CPU WATCHDOG BUT FOR EXTERNAL WATCHDOG "VIGIE" INSIDE THE T.A.
void CZoneTest::SetWatchdogEnabled(bool Enabled)
{
    if(mZTSettings->mUseModbusCC == true)
    {
        mModbusCCMgr->SetZTWatchdogEnabled(Enabled);
    }
    else
    {
        mWatchdogEnabled = Enabled;
        mExtIOWorkerThread->ClearOutputFlags(mZTStation->GetOutputMasks()->OutputWatchdogMask);
    }
}

void CZoneTest::CloseMaintenancePageRequest()
{
    panel.mMaintenancePage->hide();
    panel.mOptionsPage->show();
}

///Messages from general settings page
void CZoneTest::OpenGeneralSettingsPage()
{
	panel.mGeneralSettingsPage->show();
	panel.mOptionsPage->hide();
}

void CZoneTest::CloseGeneralSettingsPage()
{
	panel.mGeneralSettingsPage->hide();
}

void CZoneTest::UseNetworkTime(bool UseNetworkTime)
{
    mZTSettings->mUseNetworkTime = UseNetworkTime;
    mZTSettingsFileMgr.SaveSettings(mZTSettings);
}

///Messages from Modbus settings page
void CZoneTest::OpenModbusSettingsPage()
{
    panel.mModbusSettingsPage->SetActualSettings(mZTSettings->mUseModbusCC,mZTSettings->mModbusCCHostAddress);
    panel.mModbusSettingsPage->show();
    panel.mOptionsPage->hide();
}

void CZoneTest::CloseModbusSettingsPage()
{
    panel.mModbusSettingsPage->hide();
}

void CZoneTest::ModbusSettingsChangedReboot(bool UseModbus, QHostAddress CCHostAdd)
{
    mZTSettings->mUseModbusCC = UseModbus;
    mZTSettings->mModbusCCHostAddress = CCHostAdd;
    mZTSettingsFileMgr.SaveSettings(mZTSettings);

    if(mNetworkCfgMgr.SetTRCPNetworkAddress(CCHostAdd) == RET_OK)
    {
        if(mDoNotReboot == false)
        {
            ApplicationQuit(EXIT_REASON_SYSTEM_REBOOT);
        }
    }

}

//Messages from SEI settings page
void CZoneTest::OpenSEISettingsPage()
{
    panel.mSEISettingsPage->SetActualSettings(mZTSettings->mSEIModbusHostAddress);
    panel.mSEISettingsPage->show();
    panel.mOptionsPage->hide();
}

void CZoneTest::CloseSEISettingsPage()
{
    panel.mSEISettingsPage->hide();
}

void CZoneTest::ApplySEISettings(QHostAddress SEIHostAdd)
{
    mZTSettings->mSEIModbusHostAddress = SEIHostAdd;
    mZTSettingsFileMgr.SaveSettings(mZTSettings);

    mModbusSEIMgr->SEISettingsChanged(SEIHostAdd,CZTConfigMgr::instance()->GetModbusSEIPort(),CZTConfigMgr::instance()->GetModbusSEIDevID());

    //TODO: apply changes and reconnect.
}

///Messages from ZTLog viewer page
void CZoneTest::ShowZTLogViewerPage()
{
	panel.mZTLogViewerPage->show();
	panel.mOptionsPage->hide();
}

void CZoneTest::HideZTLogViewerPage()
{
	panel.mZTLogViewerPage->hide();
}

void CZoneTest::ResetTriggerCount()
{
	mZTStateMachine->ResetNbTriggers();
}

void CZoneTest::ResetNbPassages()
{
    mZTStateMachine->ResetNbPassages();
}

void CZoneTest::LogZTSettingsRequest(bool LogStationName)
{
    mZTSettingsFileMgr.LogSettings(mZTSettings,LogStationName);
}

void CZoneTest::OpenModbusDataPageRequest()
{
    panel.mEngineeringPage->hide();
    panel.mModbusDisplayPage->show();
}

void CZoneTest::CloseModbusDataPageRequest()
{
    panel.mModbusDisplayPage->hide();
    panel.mEngineeringPage->show();
}

void CZoneTest::OpenHistorienDataPageRequest()
{
    panel.mModbusDisplayPage->hide();
    panel.mHistorienDisplayPage->show();
}

void CZoneTest::CloseHistorienDataPageRequest()
{
    panel.mHistorienDisplayPage->hide();
    panel.mEngineeringPage->show();
}

void CZoneTest::CheckAndCreateDirectories()
{
	QDir dir("./Trains");
	if(dir.exists() == false)
	{
		QDir().mkdir("./Trains");
	}

	dir = QDir("./ING");
	if(dir.exists() == false)
	{
		QDir().mkdir("./ING");
	}

	dir = QDir("./LOG");
	if(dir.exists() == false)
	{
		QDir().mkdir("./LOG");
	}

	dir = QDir("./Configuration");
	if(dir.exists() == false)
	{
		QDir().mkdir("./Configuration");
	}
}

///Messages from network interface
CTCPZTStatus *CZoneTest::GetTCPStatusRequest()
{
    CTCPZTStatus *status = new CTCPZTStatus;

    status->mZT1Status = (quint32)mZTStateMachine->GetZT1ActiveStatus();
    status->mZT2Status = (quint32)mZTStateMachine->GetZT2ActiveStatus();
    status->mNbPass = (quint32)mZTStateMachine->GetNbPassages();
    status->mNbTrigs = (quint32)mZTStateMachine->GetNbTriggers();

    status->mZTStartDateTime = mZTStartDateTime;
    status->mActualDateTime = QDateTime::currentDateTime();

    status->mPGTreshold = (qint32)mZTSettings->mPGTreshold;

    status->mModeMaintenanceON = mZTStateMachine->IsInMaintenance();
    status->mCalibModeON = mZTStateMachine->IsInPGCalibration();

    status->mFNTKActive = mZTSettings->mDetectionFunctionSettings->mZTDetectionConfig[DETECTION_FCT_FN].TKActive;
    status->mFNAnalysisActive = mZTSettings->mDetectionFunctionSettings->mZTDetectionConfig[DETECTION_FCT_FN].AnalysisActive;
    status->mPGTKActive = mZTSettings->mDetectionFunctionSettings->mZTDetectionConfig[DETECTION_FCT_PG].TKActive;
    status->mPGAnalysisActive = mZTSettings->mDetectionFunctionSettings->mZTDetectionConfig[DETECTION_FCT_PG].AnalysisActive;
    status->mPP1TKActive = mZTSettings->mDetectionFunctionSettings->mZTDetectionConfig[DETECTION_FCT_PP].TKActive;
    status->mPP1AnalysisActive = mZTSettings->mDetectionFunctionSettings->mZTDetectionConfig[DETECTION_FCT_PP].AnalysisActive;
    status->mPP2TKActive = mZTSettings->mDetectionFunctionSettings->mZTDetectionConfig[DETECTION_FCT_PP2].TKActive;
    status->mPP2AnalysisActive = mZTSettings->mDetectionFunctionSettings->mZTDetectionConfig[DETECTION_FCT_PP2].AnalysisActive;
    status->mZT1TKActive = mZTSettings->mDetectionFunctionSettings->mZTDetectionConfig[DETECTION_FCT_ZT1].TKActive;
    status->mZT1AnalysisActive = mZTSettings->mDetectionFunctionSettings->mZTDetectionConfig[DETECTION_FCT_ZT1].AnalysisActive;
    status->mZT2TKActive = mZTSettings->mDetectionFunctionSettings->mZTDetectionConfig[DETECTION_FCT_ZT2].TKActive;
    status->mZT2AnalysisActive = mZTSettings->mDetectionFunctionSettings->mZTDetectionConfig[DETECTION_FCT_ZT2].AnalysisActive;

    status->mUSBKeyConnected = mUSBDriveInterface->IsDriveDetected();

    return status;  //HAVE TO BE DELETED BY CALLER !!!
}

QString *CZoneTest::GetZTLogTextRequest()
{
    QString *string = new QString(CZTLog::instance()->GetEntireLogFile());
    return string; //HAVE TO BE DELETED BY CALLER !!!
}

QFileInfoList CZoneTest::GetTrainLogsFileListRequest()
{
    return mLogMgr->GetLogsFilenameList();
}

unsigned int CZoneTest::DeleteZTLogRequest()
{
    return CZTLog::instance()->DeleteLogFile();
}

unsigned int CZoneTest::PauseInternalWatchdog()
{
    mInternalWatchdog->StopWatchdog();
    return RET_OK;
}

unsigned int CZoneTest::ResumeInternalWatchdog()
{
    mInternalWatchdog->StartWatchdog();
    return RET_OK;
}

bool CZoneTest::IsZT2PresentInStation()
{
    return mZTStation->StationHasZT2();
}

unsigned int CZoneTest::SetZTFunctionsConfig(const CTCPZTFunctionsStatus &FunctionsConfig)
{
    if(FunctionsConfig.mZT1AnalysisActive != mZTSettings->mDetectionFunctionSettings->mZTDetectionConfig[DETECTION_FCT_ZT1].AnalysisActive)
    {
        mZTSettings->mDetectionFunctionSettings->mZTDetectionConfig[DETECTION_FCT_FN].AnalysisActive = FunctionsConfig.mZT1AnalysisActive;
        mZTSettings->mDetectionFunctionSettings->mZTDetectionConfig[DETECTION_FCT_PG].AnalysisActive = FunctionsConfig.mZT1AnalysisActive;
        mZTSettings->mDetectionFunctionSettings->mZTDetectionConfig[DETECTION_FCT_PP].AnalysisActive = FunctionsConfig.mZT1AnalysisActive;
        mZTSettings->mDetectionFunctionSettings->mZTDetectionConfig[DETECTION_FCT_ZT1].AnalysisActive = FunctionsConfig.mZT1AnalysisActive;

    }
    else
    {
        mZTSettings->mDetectionFunctionSettings->mZTDetectionConfig[DETECTION_FCT_FN].AnalysisActive = FunctionsConfig.mFNAnalysisActive;
        mZTSettings->mDetectionFunctionSettings->mZTDetectionConfig[DETECTION_FCT_PG].AnalysisActive = FunctionsConfig.mPGAnalysisActive;
        mZTSettings->mDetectionFunctionSettings->mZTDetectionConfig[DETECTION_FCT_PP].AnalysisActive = FunctionsConfig.mPP1AnalysisActive;
    }
    if(FunctionsConfig.mZT2AnalysisActive != mZTSettings->mDetectionFunctionSettings->mZTDetectionConfig[DETECTION_FCT_ZT2].AnalysisActive)
    {
        mZTSettings->mDetectionFunctionSettings->mZTDetectionConfig[DETECTION_FCT_PP2].AnalysisActive = FunctionsConfig.mZT2AnalysisActive;
        mZTSettings->mDetectionFunctionSettings->mZTDetectionConfig[DETECTION_FCT_ZT2].AnalysisActive = FunctionsConfig.mZT2AnalysisActive;
    }
    else
    {
        mZTSettings->mDetectionFunctionSettings->mZTDetectionConfig[DETECTION_FCT_PP2].AnalysisActive = FunctionsConfig.mPP2AnalysisActive;
    }


    if(FunctionsConfig.mZT1TKActive != mZTSettings->mDetectionFunctionSettings->mZTDetectionConfig[DETECTION_FCT_ZT1].TKActive)
    {
        mZTSettings->mDetectionFunctionSettings->mZTDetectionConfig[DETECTION_FCT_FN].TKActive = FunctionsConfig.mZT1TKActive;
        mZTSettings->mDetectionFunctionSettings->mZTDetectionConfig[DETECTION_FCT_PG].TKActive = FunctionsConfig.mZT1TKActive;
        mZTSettings->mDetectionFunctionSettings->mZTDetectionConfig[DETECTION_FCT_PP].TKActive = FunctionsConfig.mZT1TKActive;
        mZTSettings->mDetectionFunctionSettings->mZTDetectionConfig[DETECTION_FCT_ZT1].TKActive = FunctionsConfig.mZT1TKActive;
    }
    else
    {
        mZTSettings->mDetectionFunctionSettings->mZTDetectionConfig[DETECTION_FCT_FN].TKActive = FunctionsConfig.mFNTKActive;
        mZTSettings->mDetectionFunctionSettings->mZTDetectionConfig[DETECTION_FCT_PG].TKActive = FunctionsConfig.mPGTKActive;
        mZTSettings->mDetectionFunctionSettings->mZTDetectionConfig[DETECTION_FCT_PP].TKActive = FunctionsConfig.mPP1TKActive;
    }
    if(FunctionsConfig.mZT2TKActive != mZTSettings->mDetectionFunctionSettings->mZTDetectionConfig[DETECTION_FCT_ZT2].TKActive)
    {
        mZTSettings->mDetectionFunctionSettings->mZTDetectionConfig[DETECTION_FCT_PP2].TKActive = FunctionsConfig.mZT2TKActive;
        mZTSettings->mDetectionFunctionSettings->mZTDetectionConfig[DETECTION_FCT_ZT2].TKActive = FunctionsConfig.mZT2TKActive;
    }
    else
    {
        mZTSettings->mDetectionFunctionSettings->mZTDetectionConfig[DETECTION_FCT_PP2].TKActive = FunctionsConfig.mPP2TKActive;
    }

    mZTSettingsFileMgr.SaveSettings(mZTSettings);
    panel.mFunctionSelectPage->SetConfig(mZTSettings->mDetectionFunctionSettings);
    mEventMgr->UpdateEvents(mZTSettings->mDetectionFunctionSettings);


    return RET_OK;
}

int CZoneTest::SetZT1InhibitionState(bool InhibitionON)
{
    if(InhibitionON)
    {
        mEventMgr->AddSingleEvent(EVENT_ZT1_INHIBITION);
    }
    else
    {
        mEventMgr->RemoveSingleEvent(EVENT_ZT1_INHIBITION);
    }
    return RET_OK;
}

int CZoneTest::SetZT2InhibitionState(bool InhibitionON)
{
    if(InhibitionON)
    {
        mEventMgr->AddSingleEvent(EVENT_ZT2_INHIBITION);
    }
    else
    {
        mEventMgr->RemoveSingleEvent(EVENT_ZT2_INHIBITION);
    }
    return RET_OK;
}

int CZoneTest::NewZT1Passage(CZTPassageInfo ZT1PassageInfo)
{
    if(mPIHistorianManager != 0)
    {
        mPIHistorianManager->NewZT1Passage(ZT1PassageInfo);
    }
    return RET_OK;
}

int CZoneTest::NewZT2Passage(CZTPassageInfo ZT2PassageInfo)
{
    if(mPIHistorianManager != 0)
    {
        mPIHistorianManager->NewZT2Passage(ZT2PassageInfo);
    }
    return RET_OK;
}

void CZoneTest::ApplicationQuit(int Reason)
{

    if(Reason == EXIT_REASON_USER_REQUEST)
    {
        mZtState = ZT_EXIT_APPLICATION_STATE;
    }
    else if(Reason == EXIT_REASON_POWER_BUTTON)
    {
        mZtState = ZT_POWER_BUTTON_EXIT_STATE;
    }
    else if(Reason == EXIT_REASON_SYSTEM_REBOOT)
    {
        CZTLog::instance()->AddLogString("Redémarrage de l'ordinateur suite à un changement de paramètres.");
        mZtState = ZT_SYSTEM_REBOOT_EXIT_STATE;
    }
    else
    {
        qDebug("Trying to exit app with unknown reason... Ignoring");
        return;
    }


	mExtIOWorkerThread->SetOutput((quint32)0);
	mExtIOWorkerThread->StopAcquisition();

	//Wait for the thread to stop
	while(mExtIOWorkerThread->IsThreadRunning() == true)
	{
		usleep(1000);
	}

//    if(mDI710Module != 0)
//    {
//        mDI710Module->StopThread();
//        while(mDI710Module->IsThreadRunning() == true)
//        {
//            usleep(1000);
//        }
//    }
//    mDataQThread->quit();
//    if(mDataQThread->wait(1000) == false)
//    {
//        qDebug("DataqThread wait = false");
//    }


    if(mModbusCCMgr != 0)
    {
        if(mModbusCCMgr->CloseModbusCCServer() != 0)
        {
            qDebug("Modbus server closed");
        }
    }



	//	qDebug("Creating escape file...");
    system("echo exit > ./Escape.ZT");	//Crée un fichier vide pour informer le script de ne pas redémarrer l'application
    system("sync");

	mExtIOThread->quit();
	if(mExtIOThread->wait(1000) == false)
	{
        qDebug("ExtIOThread wait = false");
	}
}

void CZoneTest::ACPISocketConnected()
{
    CEngLog::instance()->AddLogString("Socket ACPI connecté");
}

void CZoneTest::ACPISocketEvent()
{

    QString Res(mACPISocket.readAll());
    if(Res.contains("button/power"))
    {
        CZTLog::instance()->AddLogString("Activation du bouton << Power >>, sortie du programme",true);
        mACPISocket.close();
        ApplicationQuit(EXIT_REASON_POWER_BUTTON);
    }
    else
    {
        Res.prepend("Événement ACPI inconnu: ");
        CZTLog::instance()->AddLogString(Res);
    }
}


void CZoneTest::ModbusDateTimeUpdate(QDateTime *NewDateTime)
{
    if(mZTSettings->mUseNetworkTime == true)
    {
        if(*NewDateTime != QDateTime::currentDateTime())
        {
            CEngLog::instance()->AddLogString("Synchronisation de l'heure avec le SACL");
            //CZTLog::instance()->AddLogString("Synchronisation de l'heure avec le SACL");
            SetSystemDateTime(NewDateTime);
        }
    }
}

int CZoneTest::SetSystemDateTime(QDateTime *DateTime)
{
    time_t time_data = time(0);
    struct tm* tm_ptr = localtime(&time_data);

    tm_ptr->tm_min = DateTime->time().minute();
    tm_ptr->tm_hour = DateTime->time().hour();
    tm_ptr->tm_mday = DateTime->date().day();
    tm_ptr->tm_mon = DateTime->date().month()-1;
    tm_ptr->tm_year = DateTime->date().year()-1900;

    const struct timeval tv = {mktime(tm_ptr),0};
    if(settimeofday(&tv,0) < 0)
    {
        qDebug("Settimeofday failed");
        CZTLog::instance()->AddLogString("Échec du changement de la date & de l'heure",true);
        return RET_ERROR;
    }
    else
    {
        if ( system("/sbin/hwclock --systohc") < 0 )
        {
            //qDebug("hwclock sync failed");
            CZTLog::instance()->AddLogString("Échec du changement de la date & de l'heure (hwsync failure)",true);
            return RET_ERROR;
        }
        else
        {
            CEngLog::instance()->AddLogString(QString().sprintf("Changement de date & heure: %s %s",DateTime->date().toString("yyyy/MM/dd").toUtf8().data(),DateTime->time().toString("hh:mm").toUtf8().data()));
           // CZTLog::instance()->AddLogString(QString().sprintf("Changement de date & heure: %s %s",DateTime->date().toString("yyyy/MM/dd").toUtf8().data(),DateTime->time().toString("hh:mm").toUtf8().data()),true);
        }
    }
    return RET_OK;
}





