/*******************************************************************************
*                                                                              *
* 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 "OutilZT.h"
#include <QApplication>
#include <QTextCodec>
//#include "NetworkManager.h"

#include <QByteArray>
#include <QDebug>
#include <QMessageBox>


COutilZT::COutilZT()
{
    panel.installEventFilter(this);	//Install an event filter for CZoneTest to manage some events from GUI

}
COutilZT::~COutilZT()
{
}



unsigned int COutilZT::Start()
{
  //  QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));


    panel.mDatabaseModeLogListPage->mLogMgrHandle = &mDatabaseModeLogManager;
    panel.mDatabaseModeLogListPage->mProgramHandle = this;
    panel.mMainPage->mProgramHandle = this;
    panel.mOptionsPage->mProgramHandle = this;
    if(mIsEngMode == true)
    {
        panel.mOptionsPage->EnableEngineeringMode();
    }
    panel.mNetworkCtrlPage->mProgramHandle = this;
    panel.mDatabaseMgrPage->mProgramHandle = this;
    panel.mDatabaseMgrPage->mLogMgrHandle = &mDatabaseModeLogManager;
    panel.mDatabaseMgrPage->mZTLogFilesManager = &mZTLogFilesManager;
    if(mIsEngMode == true)
    {
        panel.mDatabaseMgrPage->EnableEngineeringMode();
    }
    if(mCanImport == true)
    {
        panel.mDatabaseMgrPage->EnableLogImport();
    }

    mDatabaseModeLogManager.mProgramHandle = this;
    panel.mNetworkModeLogListPage->mProgramHandle = this;
    panel.mNetworkModeLogListPage->mLogMgrHandle = &mNetworkModeLogManager;
    panel.mNetworkModeLogViewPage->mProgramHandle = this;
    mNetworkModeLogManager.mProgramHandle = this;
    panel.mRemoteZTCtrlPage->mProgramHandle = this;
    panel.mZTLogsListPage->mProgramHandle = this;
    panel.mZTLogsListPage->mZTLogFilesManager = &mZTLogFilesManager;
    if(mIsEngMode == true)
    {
        panel.mDatabaseModeLogListPage->EnableEngineeringMode();
        panel.mNetworkModeLogListPage->EnableEngineeringMode();
    }




    mSettingsFileMgr.LoadSettings(&mSettingsData);

    panel.mOptionsPage->mLogsPathText->setPlainText(mSettingsData.mDataSourceDirectoryPath);


//    CNetworkManager::instance()->BindPointers(this);
//    CNetworkManager::instance()->SetConfig(&mSettingsData);
//    panel.mNetworkZTListPage->SetConfig(&mSettingsData);
//    panel.mOptionsPage->SetSettings(&mSettingsData);
//    connect(CNetworkManager::instance(),SIGNAL(NetworkZTConnectionStatus(int,int)),panel.mNetworkZTListPage,SLOT(ZTNetworkStatusChanged(int,int)));
//    connect(CNetworkManager::instance(),SIGNAL(NetworkZTConnected(int)),panel.mNetworkCtrlPage,SLOT(NetworkZTConnected(int)));
//    connect(CNetworkManager::instance(),SIGNAL(NetworkZTConnectionError(int)),panel.mNetworkCtrlPage,SLOT(NetworkZTConnectionFailed(int)));
//    connect(CNetworkManager::instance(),SIGNAL(NetworkZTDisconnected(int)),panel.mNetworkCtrlPage,SLOT(NetworkZTConnectionFailed(int)));
//    connect(CNetworkManager::instance(),SIGNAL(NetworkTCPRx()),panel.mNetworkCtrlPage,SLOT(NetworkRx()));
//    connect(CNetworkManager::instance(),SIGNAL(NetworkTCPTx()),panel.mNetworkCtrlPage,SLOT(NetworkTx()));

//    connect(CNetworkManager::instance(),SIGNAL(NetworkZTConnected(int)),panel.mRemoteZTPage,SLOT(NetworkZTConnected(int)));
//    connect(CNetworkManager::instance(),SIGNAL(NetworkZTDisconnected(int)),panel.mRemoteZTPage,SLOT(NetworkZTDisconnected(int)));

//    panel.mDatabaseModeLogListPage->RefreshList();
//    panel.mZTLogsListPage->RefreshList();

    //Show Graphic User Interface.
    panel.setWindowTitle("Outil Zone Test");
    panel.show();


    mDatabaseModeLogManager.mProgramHandle = this;
    mDatabaseModeLogManager.SetLogDataDir(GetLogDataPath());
    mDatabaseModeLogManager.ParseLogs();
    mNetworkModeLogManager.mProgramHandle = this;
    mNetworkModeLogManager.SetLogDataDir(GetTrainLogsTempPath());
 //   mNetworkModeLogManager.ParseLogs();
    mZTLogFilesManager.mProgramHandle = this;
    mZTLogFilesManager.SetLogDataDir(GetLogDataPath());
    mZTLogFilesManager.ParseZTLogFiles(false);

    mOutilZTMode = MODE_INVALID;
  //  EnterNetworkModeRequest();
    EnterDatabaseModeRequest();

    mRebuildingDB = false;

 //   CNetworkManager::instance()->CheckZTConnectionsStatus();




    return RET_OK;
}


unsigned int COutilZT::InitZT()
{
    return RET_OK;
}

void COutilZT::LogViewRequest(CLogElement *element, CLogsListPage *caller)
{
    if(caller == panel.mDatabaseModeLogListPage)
    {
        panel.mDatabaseModeLogViewPage->SetLogData(element);
    }
    else if(caller == panel.mNetworkModeLogListPage)
    {
        panel.mNetworkModeLogViewPage->SetLogData(element);
        ShowNetworkModeLogViewRequest();
    }
}

unsigned int COutilZT::SetLogProtection(bool Protection, CLogElement* Element, CLogsListPage *Caller)
{
    if(Caller == panel.mDatabaseModeLogListPage)
    {
        if(mDatabaseModeLogManager.ProtectLogElementFile(Protection,Element) == RET_OK)
        {
            return RET_OK;
        }
    }

    return RET_ERROR;
}


void COutilZT::LogViewCloseRequest(CLogViewPage *caller)
{
    if(caller == panel.mNetworkModeLogViewPage)
    {
        HideNetworkModeLogViewRequest();
    }
}

void COutilZT::ShowOptionsRequest()
{
    panel.mOptionsPage->show();
}

void COutilZT::HideOptionsRequest()
{
    panel.mOptionsPage->hide();
}

void COutilZT::ShowDatabaseMgrRequest()
{
    panel.mDatabaseMgrPage->show();
}

void COutilZT::HideDatabaseMgrRequest()
{
    panel.mDatabaseMgrPage->hide();
}

void COutilZT::EnterDatabaseModeRequest()
{
    if(mOutilZTMode == MODE_DATABASE)
        return;

    panel.mNetworkZTListPage->hide();
    panel.mNetworkCtrlPage->hide();
    panel.mRemoteZTPage->hide();
    panel.mNetworkModeLogListPage->hide();
    panel.mNetworkModeLogViewPage->hide();
    panel.mRemoteZTCtrlPage->hide();

    panel.mZTLogsListPage->hide();
    panel.mZTLogFileViewerPage->hide();

    panel.mDatabaseModeLogListPage->show();
    panel.mDatabaseModeLogViewPage->show();







    mOutilZTMode = MODE_DATABASE;
}

void COutilZT::EnterNetworkModeRequest()
{
    if(mOutilZTMode == MODE_NETWORK)
        return;

    panel.mDatabaseModeLogListPage->hide();
    panel.mDatabaseModeLogViewPage->hide();

    panel.mNetworkZTListPage->show();
    panel.mNetworkCtrlPage->show();
    panel.mRemoteZTPage->show();
    panel.mNetworkModeLogListPage->show();
    panel.mNetworkModeLogViewPage->hide();
    panel.mRemoteZTCtrlPage->hide();

    panel.mZTLogsListPage->hide();
    panel.mZTLogFileViewerPage->hide();

    mOutilZTMode = MODE_NETWORK;
}

void COutilZT::EnterZTLogModeRequest()
{
    if(mOutilZTMode == MODE_ZTLOG)
        return;

    panel.mDatabaseModeLogListPage->hide();
    panel.mDatabaseModeLogViewPage->hide();

    panel.mNetworkZTListPage->hide();
    panel.mNetworkCtrlPage->hide();
    panel.mRemoteZTPage->hide();
    panel.mNetworkModeLogListPage->hide();
    panel.mNetworkModeLogViewPage->hide();
    panel.mRemoteZTCtrlPage->hide();

    panel.mZTLogsListPage->show();
    panel.mZTLogFileViewerPage->show();


    mOutilZTMode = MODE_ZTLOG;


}

void COutilZT::ShowZTLogRequest(QString Log,QString FocusText,int line)
{
    panel.mZTLogViewerPage->SetZTLogText(Log,FocusText);
    if(line != -1)
        panel.mZTLogViewerPage->ScrollToLine(line);

    panel.mZTLogViewerPage->show();
}

void COutilZT::ShowNetworkModeLogViewRequest()
{
  //  panel.mRemoteZTPage->hide();
    panel.mNetworkModeLogListPage->hide();
    panel.mNetworkModeLogViewPage->show();
}

void COutilZT::HideNetworkModeLogViewRequest()
{
//    panel.mRemoteZTPage->show();
    panel.mNetworkModeLogListPage->show();
    panel.mNetworkModeLogViewPage->hide();
}

void COutilZT::ShowRemoteControlPage()
{
    panel.mRemoteZTPage->show();
    panel.mNetworkModeLogListPage->hide();
    panel.mNetworkModeLogViewPage->hide();
    panel.mRemoteZTCtrlPage->show();
}

void COutilZT::ShowRemoteTrainLogsViewPages()
{
    panel.mRemoteZTPage->show();
    panel.mNetworkModeLogListPage->show();
    panel.mNetworkModeLogViewPage->hide();
    panel.mRemoteZTCtrlPage->hide();
}
void COutilZT::ShowRemoteLiveZTPage()
{
    panel.mRemoteZTPage->hide();
    panel.mNetworkModeLogListPage->hide();
    panel.mNetworkModeLogViewPage->hide();
    panel.mRemoteZTCtrlPage->hide();
}

QString COutilZT::GetLogDataPath()
{
    return mSettingsData.mDataSourceDirectoryPath;
}

QString COutilZT::GetTrainLogsTempPath()
{
    return QString("./Temp/");
}

void COutilZT::CleanTrainLogsTempPath()
{
    QDir TrainLogsTempDir(GetTrainLogsTempPath());

    TrainLogsTempDir.setFilter(QDir::Files | QDir::NoDotAndDotDot);
    QFileInfoList fileslist = TrainLogsTempDir.entryInfoList();
    for(int i = 0; i < fileslist.size(); i++)
    {
        QDir().remove(fileslist.at(i).filePath());
    }
}

unsigned int COutilZT::DataSourceDirChanged(QString NewPath)
{
    mSettingsData.mDataSourceDirectoryPath = NewPath;
    mSettingsFileMgr.SaveSettings(&mSettingsData);
    mDatabaseModeLogManager.SetLogDataDir(NewPath);
    mZTLogFilesManager.SetLogDataDir(NewPath);
    LogsDatabaseChanged(0);

    return RET_OK;
}

unsigned int COutilZT::NetworkDataChanged()
{
    mSettingsFileMgr.SaveSettings(&mSettingsData);

    //todo: Notify network manager...
    return RET_OK;
}

unsigned int COutilZT::LogsDatabaseChanged(QStringList *NewLogs)
{
    if(NewLogs == 0)
    {
        mDatabaseModeLogManager.ParseLogs(true,false);
    }
    else
    {
        mDatabaseModeLogManager.ParseImportedLogs(NewLogs);
    }


//    ZTLogFilesChanged();
    mZTLogFilesManager.ParseZTLogFiles(true);
    return RET_OK;
}

unsigned int  COutilZT::RebuildDatabaseFile()
{
    mDatabaseModeLogManager.ParseLogs(true,false);
  //  mRebuildingDB = true;
    mZTLogFilesManager.ParseZTLogFiles(true);
    return RET_OK;
}

unsigned int COutilZT::LogsDatabaseLoaded(CLogMgr *Caller, int Status)
{
    if(Caller == &mDatabaseModeLogManager)
    {
      // QMessageBox::information(0,"Parsing Finished","Parsing finished");
        if(Status == 1)
        {
           panel.mDatabaseModeLogListPage->RefreshList();
           panel.mDatabaseMgrPage->UpdateDBStats();
//           if(mRebuildingDB)
//           {
//               mZTLogFilesManager.ParseZTLogFiles(true);
//               mRebuildingDB = false;
//           }
        }
        else
        {
           QMessageBox::information(0,"Erreur","Impossible de charger la base de données");
        }
       panel.mProgressBarPage->hide();
    }
    if(Caller == &mNetworkModeLogManager)
    {
        panel.mNetworkModeLogListPage->RefreshList();
    }

    return RET_OK;
}

unsigned int COutilZT::UpdateLogsList(CLogMgr *Caller)
{
    if(Caller == &mDatabaseModeLogManager)
    {
       panel.mDatabaseModeLogListPage->RefreshList();
    }
    if(Caller == &mNetworkModeLogManager)
    {
        panel.mNetworkModeLogListPage->RefreshList();
    }
    return RET_OK;
}

unsigned int COutilZT::DatabaseFetchingBegin(CLogMgr *Caller)
{
    if(Caller == &mDatabaseModeLogManager)
    {
        panel.mProgressBarPage->SetProgressBarRange(0);
        panel.mProgressBarPage->SetTitle("Chargement de la base de données");
        panel.mProgressBarPage->SetMiscLabel("");
        panel.mProgressBarPage->show();
    }
    return RET_OK;
}

unsigned int COutilZT::DatabaseFetchingTick(CLogMgr *Caller,int Index)
{
//    qDebug() << "Rx new Train Log: " << FileName;

    if(Caller == &mDatabaseModeLogManager)
    {
        panel.mProgressBarPage->Tick();
        panel.mProgressBarPage->SetMiscLabel(QString("%1 passages chargés").arg(Index));
    }

    return RET_OK;
}


unsigned int COutilZT::ZTLogFilesChanged()
{
    mZTLogFilesManager.SaveDatabaseFile();
    mZTLogFilesManager.ParseZTLogFiles(false);


    return RET_OK;
}



unsigned int COutilZT::ShowZTLogFile(QString FilePath)
{
    panel.mZTLogFileViewerPage->SetZTLogText(FilePath);
    return RET_OK;
}

unsigned int COutilZT::ZTLogFilesDatabaseLoaded(CZTLogFilesMgr *Caller, int Status)
{
    if(Caller == &mZTLogFilesManager)
    {
        if(Status == 1)
        {
            panel.mZTLogsListPage->RefreshList();
            panel.mDatabaseMgrPage->UpdateDBStats();
//            panel.mProgressBarPage->hide();
        }
        else
        {
           // QMessageBox::information(0,"Parsing failed","Parsing failed");
        }
    }

    return RET_OK;
}

unsigned int COutilZT::ZTLogFilesFetchingBegin(CZTLogFilesMgr *Caller)
{
    if(Caller == &mZTLogFilesManager)
    {
//        panel.mProgressBarPage->SetProgressBarRange(0);
//        panel.mProgressBarPage->SetTitle("Chargement des fichiers LOG");
//        panel.mProgressBarPage->SetMiscLabel("");
//        panel.mProgressBarPage->show();
    }
    return RET_OK;

}

unsigned int COutilZT::ZTLogFilesFetchingTick(CZTLogFilesMgr *Caller, int Index, QString File)
{
    if(Caller == &mZTLogFilesManager)
    {
//        panel.mProgressBarPage->Tick();
//        panel.mProgressBarPage->SetMiscLabel(QString("%1 passages chargés : %2").arg(Index).arg(File));
    }

    return RET_OK;
}

unsigned int COutilZT::ConnectToZTRequest()
{
    int ID = panel.mNetworkZTListPage->GetSelectedZT();
 //   CNetworkManager::instance()->ConnectToZT(ID);
    return RET_OK;
}

unsigned int COutilZT::RxStationName(QString StationName)
{
    panel.mRemoteZTPage->SetRemoteZTName(StationName);
    return RET_OK;
}

unsigned int COutilZT::DisconnectZTRequest()
{
  //  return CNetworkManager::instance()->DisconnectZT();
}

unsigned int COutilZT::RefreshRemoteZTStatusRequest()
{

//    if(CNetworkManager::instance()->RefreshRemoteZTStatus() == RET_OK)
//    {
//        panel.mNetworkCtrlPage->DisableNetworkButtons();
//        return RET_OK;
//    }

    return RET_ERROR;
}

unsigned int COutilZT::RxZTStatus(const CTCPZTStatus &status)
{
    panel.mNetworkCtrlPage->EnableNetworkButtons();
    panel.mRemoteZTPage->SetRemoteZTStatus(&status);
    panel.mRemoteZTCtrlPage->UpdateDisplay(&status);
    return RET_OK;
}

unsigned int COutilZT::DownloadZTLogRequest()
{
//    if(CNetworkManager::instance()->DownloadZTLog() == RET_OK)
//    {
//        panel.mNetworkCtrlPage->DisableNetworkButtons();
//        return RET_OK;
//    }
    return RET_ERROR;
}

unsigned int COutilZT::RxZTLog(QString ZTLog)
{
    panel.mNetworkCtrlPage->EnableNetworkButtons();
    panel.mZTLogViewerPage->SetZTLogText(ZTLog);
    panel.mZTLogViewerPage->show();
    return RET_OK;
}

unsigned int COutilZT::DownloadTrainLogsRequest()
{
//    if(CNetworkManager::instance()->DownloadTrainLogs() == RET_OK)
//    {
//        panel.mNetworkCtrlPage->DisableNetworkButtons();
//        return RET_OK;
//    }

    return RET_ERROR;
}

unsigned int COutilZT::DownloadTrainLogsBegin(int NbLogs)
{
    CleanTrainLogsTempPath();
    panel.mProgressBarPage->SetProgressBarRange(NbLogs);
    panel.mProgressBarPage->SetTitle(QString("Réception de %1 fichiers").arg(NbLogs));
    panel.mProgressBarPage->SetMiscLabel("");
    panel.mProgressBarPage->show();

    return RET_OK;
}

unsigned int COutilZT::RxTrainLogData(QString FileName)
{

    qDebug() << "Rx new Train Log: " << FileName;
    panel.mProgressBarPage->Tick();
    panel.mProgressBarPage->SetMiscLabel(QString("Réception: %1").arg(FileName));
    return RET_OK;


}

unsigned int COutilZT::RxTrainLogsDownloadFinished()
{
    panel.mNetworkCtrlPage->EnableNetworkButtons();
    qDebug("TrainLogs download finished");
    mNetworkModeLogManager.ParseLogs();
    panel.mNetworkModeLogListPage->RefreshList();
    panel.mProgressBarPage->hide();

    return RET_OK;
}

unsigned int COutilZT::DeleteRemoteZTLogRequest()
{
//    if(CNetworkManager::instance()->DeleteRemoteZTLog() == RET_OK)
//    {
//        panel.mNetworkCtrlPage->DisableNetworkButtons();
//        return RET_OK;
//    }
    return RET_ERROR;
}

unsigned int COutilZT::RemoteZTLogDeleted(bool Success)
{
    panel.mNetworkCtrlPage->EnableNetworkButtons();
    return RET_OK;
}

unsigned int COutilZT::SetZTFunctionsStatus(CTCPZTFunctionsStatus status)
{
//    if(CNetworkManager::instance()->SetZTFunctions(status) == RET_OK)
//    {
//        panel.mNetworkCtrlPage->DisableNetworkButtons();
//        return RET_OK;
//    }
    return RET_ERROR;
}

unsigned int COutilZT::SetZTFunctionsSatusDone(bool succes)
{
    panel.mNetworkCtrlPage->EnableNetworkButtons();
    return RET_OK;
}

//Catch and manage some events from the graphics user interface
//like the keyboard Exit sequence (Ctrl-F10)
bool COutilZT::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)
            {
                QApplication::exit(78);	//Quit the application
                return true;	//keep the keystroke
            }
        }
    }

    return QObject::eventFilter(obj,event);

}

QString COutilZT::GetStationName(int StationID)
{
    switch(StationID)
    {
        case ANGRIGNON_ZT_ID:
        {
            return QString("Angrignon");
            break;
        }
        case HONORE_BEAUGRAND_ZT_ID:
        {
            return QString("Honoré-Beaugrand");
            break;
        }
        case LONGUEUIL_ZT_ID:
        {
            return QString("Longueuil");
            break;
        }
        case BERRI_UQAM_ZT_ID:
        {
            return QString("Berri-UQAM");
            break;
        }
        case SNOWDON_ZT_ID:
        {
            return QString("Snowdon");
            break;
        }
        case SAINT_MICHEL_ZT_ID:
        {
            return QString("Saint-Michel");
            break;
        }
        case COTE_VERTU_ZT_ID:
        {
            return QString("Côte-Vertu");
            break;
        }
        case HENRI_BOURASSA_ZT_ID:
        {
            return QString("Henri-Bourassa");
            break;
        }
        case MONTMORENCY_ZT_ID:
        {
            return QString("Montmorency");
            break;
        }
        case MONTMORENCY_10_12_ZT_ID:
        {
            return QString("Montmorency 10/12");
            break;
        }
        case MONTMORENCY_10_22_ZT_ID:
        {
            return QString("Montmorency 10/22");
            break;
        }
    }
    return QString("Unknown !!!");
}
