
#include "ZTLogFilesMgr.h"
#include <QFileInfo>
#include <QTextStream>
#include "OutilZT.h"
#include <QCoreApplication>
#include <QMessageBox>
#include <QBuffer>

CZTLogFilesMgr::CZTLogFilesMgr()
{

    mProgramHandle = 0;

    mDirParserThread = new QThread();
    mDirParserWorkerThread = new CDirParserThread();
    mDirParserWorkerThread->moveToThread(mDirParserThread);
    connect(mDirParserThread,SIGNAL(started()),mDirParserWorkerThread,SLOT(ParseDirectories()));
    connect(mDirParserThread,SIGNAL(finished()),this,SLOT(ThreadQuit()));
    connect(mDirParserThread,SIGNAL(terminated()),this,SLOT(ThreadTerminated()));
    connect(mDirParserWorkerThread,SIGNAL(NewLogParsed(QString,bool)),this,SLOT(NewZTLogParsed(QString,bool)));
    connect(mDirParserWorkerThread,SIGNAL(ParsingFinished(int)),this,SLOT(DirParsingFinished(int)));
    connect(mDirParserWorkerThread,SIGNAL(EmptyDirParsed()),this,SLOT(EmptyDirParsed()));

    mDatabaseParsingTimer = new QTimer();
    mDatabaseParsingTimer->setInterval(60000);
    connect(mDatabaseParsingTimer,SIGNAL(timeout()),this,SLOT(ParsingTimerExpired()));

    mSaveDBFile = false;
}

CZTLogFilesMgr::~CZTLogFilesMgr()
{
    delete mDirParserThread;
    delete mDirParserWorkerThread;
    delete mDatabaseParsingTimer;
}


void CZTLogFilesMgr::DestroyZTLogFilesList()
{
    mZTLogFilesList.clear();
}

void CZTLogFilesMgr::ParseZTLogFiles(bool RebuildDatabase)
{
    mZTLogFilesList.clear();

    if(RebuildDatabase == true)
    {
        mSaveDBFile = true;
        mDirParserWorkerThread->SetParsingInfo(QDir(mLogDatabaseDir),"*.txt",false);
        mDirParserThread->start();
        mProgramHandle->ZTLogFilesFetchingBegin(this);
        return ;
    }
    else
    {
        QDir BaseDir(mLogDatabaseDir);
        QString DatabaseFilePath = BaseDir.filePath("ZTLogs.zdb");
       // DatabaseFilePath += "Trains.zdb";
        QFile* DatabaseFile = new QFile(BaseDir.filePath("ZTLogs.zdb")/*DatabaseFilePath*/);


        if(DatabaseFile)
        {
            if(DatabaseFile->open(QIODevice::ReadOnly | QIODevice::Unbuffered) == false)
            {
                mSaveDBFile = true;
                mDirParserWorkerThread->SetParsingInfo(QDir(mLogDatabaseDir),"*.txt",false);
                mDirParserThread->start();
                mProgramHandle->ZTLogFilesFetchingBegin(this);

                delete DatabaseFile;
                return ;
            }
        }
        else
        {
            QMessageBox::information(0,"Erreur","Impossible de créer le fichier DB ZTLog");
            return ;
        }

        QByteArray DBData = DatabaseFile->readAll();
        QDataStream *DBStrm = new QDataStream(DBData);
        DBStrm->setVersion(QDataStream::Qt_4_8);

        qint32 NBRecords;
        *DBStrm >> NBRecords;

        for(qint32 i = 0; i < NBRecords; i++)
        {
            CZTLogFileInfo NewElement;

            *DBStrm >> NewElement.mStationName
                    >> NewElement.mZTStationID
                    >> NewElement.mStartDateTime
                    >> NewElement.mEndDateTime
                    >> NewElement.mZTLogFilePath;

            mZTLogFilesList.append(NewElement);
        }

        DatabaseFile->close();
        delete DatabaseFile;
        delete DBStrm;

        DirParsingFinished(1);



    }
}

void CZTLogFilesMgr::NewZTLogParsed(QString FilePath, bool KeepData)
{
    Q_UNUSED(KeepData)

    mProgramHandle->ZTLogFilesFetchingTick(this,mZTLogFilesList.size(),FilePath);
    ExtractLogInfo(FilePath);
    mDatabaseParsingTimer->start();
}

void CZTLogFilesMgr::DirParsingFinished(int Res)
{
    qDebug("ZTLog Files Parsing finished with result %d",Res);
    mDirParserThread->quit();
    mDatabaseParsingTimer->stop();
    mProgramHandle->ZTLogFilesDatabaseLoaded(this,Res);
     qDebug("Parsed %d ZTLog files",mZTLogFilesList.size());

     if(mSaveDBFile == true)
     {
         SaveDatabaseFile();
     }
}

int CZTLogFilesMgr::GetZTLogFilesCount()
{
    return mZTLogFilesList.size();
}

void CZTLogFilesMgr::ParsingTimerExpired()
{
    qDebug("ZTLogs Parsing timer timeout");
    mDirParserWorkerThread->KillThread();
    mDirParserThread->terminate();
    DirParsingFinished(2);
}

void CZTLogFilesMgr::EmptyDirParsed()
{
    //The thread is not stuck.  Kick the timer...
    mDatabaseParsingTimer->start();
}

void CZTLogFilesMgr::ThreadQuit()
{
  //  qDebug("Thread quit slot");
}

void CZTLogFilesMgr::ThreadTerminated()
{
 //   qDebug("Thread terminated slot");
}


bool CZTLogFilesMgr::ExtractLogInfo(QString LogFilePath)
{
    QFileInfo LogFileInfo(LogFilePath);

    if(LogFileInfo.fileName() != "ZTLog.txt" &&
       LogFileInfo.fileName() != "LogZT.txt")
        return false;

    CZTLogFileInfo NewLogFileInfo;


    int line =0;
    QFile *LogFile = new QFile(LogFilePath);
    if(LogFile)
    {
        if(LogFile->open(QIODevice::ReadOnly | QIODevice::Text | QIODevice::Unbuffered) == true)
        {
            QString LogText(LogFile->readAll());

            QTextStream strm(&LogText);
            strm.seek(0);

            QString temp;

            //find a valid line
            do
            {
                temp = strm.readLine();
                line++;

                if(strm.atEnd())
                    break;
            }
            while(temp.length() < 10);

           // temp = strm.readLine();
            QStringList parts = temp.split(" : ");
            QString LineText,DateString;


            if(parts.size() != 0)
            {
                LineText.clear();

                DateString = parts.at(0);
                NewLogFileInfo.mStartDateTime = QDateTime::fromString(DateString,"yyyy/MM/dd - hh:mm:ss.zzz");
            }

            //go to end of file
            QString LastValidLine;
            do
            {
                temp = strm.readLine();
                if(temp.size() >=10)
                    LastValidLine = temp;
            }
            while(!strm.atEnd());

            parts = LastValidLine.split(" : ");

            if(parts.size() != 0)
            {                
                DateString = parts.at(0);
                NewLogFileInfo.mEndDateTime = QDateTime::fromString(DateString,"yyyy/MM/dd - hh:mm:ss.zzz");
            }
            LogFile->close();
        }
        delete LogFile;
    }
    else
    {
        return false;
    }

    NewLogFileInfo.mZTLogFilePath = LogFilePath;

    if(LogFilePath.contains("ANG"))
    {
        NewLogFileInfo.mZTStationID = ANGRIGNON_ZT_ID;
        NewLogFileInfo.mStationName = mProgramHandle->GetStationName(ANGRIGNON_ZT_ID);// "Angrignon";
    }
    else if(LogFilePath.contains("BUQ4"))
    {
        NewLogFileInfo.mZTStationID = BERRI_UQAM_ZT_ID;
        NewLogFileInfo.mStationName = mProgramHandle->GetStationName(BERRI_UQAM_ZT_ID);//"Berri-UQAM";
    }
    else if(LogFilePath.contains("HBOU"))
    {
        NewLogFileInfo.mZTStationID = HENRI_BOURASSA_ZT_ID;
        NewLogFileInfo.mStationName = mProgramHandle->GetStationName(HENRI_BOURASSA_ZT_ID);//"Henri-Bourassa";
    }
    else if(LogFilePath.contains("HBGR"))
    {
        NewLogFileInfo.mZTStationID = HONORE_BEAUGRAND_ZT_ID;
        NewLogFileInfo.mStationName = mProgramHandle->GetStationName(HONORE_BEAUGRAND_ZT_ID);//"Honoré-Beaugrand";
    }
    else if(LogFilePath.contains("LONG"))
    {
        NewLogFileInfo.mZTStationID = LONGUEUIL_ZT_ID;
        NewLogFileInfo.mStationName = mProgramHandle->GetStationName(LONGUEUIL_ZT_ID);//"Longueuil";
    }
    else if(LogFilePath.contains("MMOY"))
    {
        NewLogFileInfo.mZTStationID = MONTMORENCY_ZT_ID;
        NewLogFileInfo.mStationName = mProgramHandle->GetStationName(MONTMORENCY_ZT_ID);//"Montmorency";
    }
    else if(LogFilePath.contains("MMO"))
    {
        NewLogFileInfo.mZTStationID = MONTMORENCY_10_12_ZT_ID;
        NewLogFileInfo.mStationName = mProgramHandle->GetStationName(MONTMORENCY_10_12_ZT_ID);//"Montmorency 10/12";
    }
    else if(LogFilePath.contains("MMO2"))
    {
        NewLogFileInfo.mZTStationID = MONTMORENCY_10_22_ZT_ID;
        NewLogFileInfo.mStationName = mProgramHandle->GetStationName(MONTMORENCY_10_22_ZT_ID);///"Montmorency 10/22";
    }
    else if(LogFilePath.contains("SMIC"))
    {
        NewLogFileInfo.mZTStationID = SAINT_MICHEL_ZT_ID;
        NewLogFileInfo.mStationName = mProgramHandle->GetStationName(SAINT_MICHEL_ZT_ID);//"Saint-Michel";
    }
    else if(LogFilePath.contains("SNW5"))
    {
        NewLogFileInfo.mZTStationID = SNOWDON_ZT_ID;
        NewLogFileInfo.mStationName = mProgramHandle->GetStationName(SNOWDON_ZT_ID);//"Snowdon";
    }
    else
    {
        return false;
    }

    mZTLogFilesList.append(NewLogFileInfo);

    return true;
}

int CZTLogFilesMgr::ParseDir(QDir dir)
{

    QStringList LogFilters;
    QFileInfoList list;
   // QString LogDataDir = mProgramHandle->GetLogDataPath();
    LogFilters << "*.txt";

    //Load files in base directory
    QDir LogDir(dir);
    LogDir.setFilter(QDir::Files | QDir::NoDotAndDotDot);
    LogDir.setNameFilters(LogFilters);
    LogDir.setSorting(QDir::Name);
    list = LogDir.entryInfoList();
    if(list.size() != 0)
    {
        //Extract data for each passage
        for(int i = 0; i < list.size(); i++)
        {
            ExtractLogInfo(list.at(i).absoluteFilePath());
        }
    }


    //Check for subdirectories
    QDir SubDirectories(dir);

    SubDirectories.setFilter(QDir::Dirs | QDir::NoDotAndDotDot);

    QFileInfoList SubDirList = SubDirectories.entryInfoList();
    for(int i = 0; i < SubDirList.size(); i++)
    {
        ParseDir(QDir(SubDirList.at(i).absoluteFilePath()));
    }

    return 1;
}

int CZTLogFilesMgr::SaveDatabaseFile()
{
    qDebug("Saving ZTLogs.zdb database");
    QDir BaseDir(mLogDatabaseDir);
    QString DatabaseFilePath = BaseDir.filePath("ZTLogs.zdb");
   // DatabaseFilePath += "Trains.zdb";
    QFile* DatabaseFile = new QFile(BaseDir.filePath("ZTLogs.zdb")/*DatabaseFilePath*/);


    if(DatabaseFile)
    {
        if(DatabaseFile->open(QIODevice::WriteOnly | QIODevice::Unbuffered) == false)
        {
            QMessageBox::information(0,"Erreur","Impossible de créer le fichier DB ZTLog");
            delete DatabaseFile;
            return RET_ERROR;
        }
    }
    else
    {
        QMessageBox::information(0,"Erreur","Impossible de créer le fichier DB ZTLog");
        return RET_ERROR;
    }


    QByteArray byteArray;
    QBuffer FileBuffer(&byteArray);
    FileBuffer.open(QIODevice::WriteOnly);
    QDataStream *DBStrm = new QDataStream(&FileBuffer);
    DBStrm->setVersion(QDataStream::Qt_4_8);

    qint32 NBRecords = mZTLogFilesList.size();
    *DBStrm << NBRecords;

    for(int i = 0; i < mZTLogFilesList.size(); i++)
    {
        *DBStrm << mZTLogFilesList.at(i).mStationName
                << mZTLogFilesList.at(i).mZTStationID
                << mZTLogFilesList.at(i).mStartDateTime
                << mZTLogFilesList.at(i).mEndDateTime
                << mZTLogFilesList.at(i).mZTLogFilePath;
    }

    FileBuffer.seek(0);
    DatabaseFile->write(FileBuffer.buffer());
    DatabaseFile->flush();

    FileBuffer.close();
    DatabaseFile->close();
    delete DatabaseFile;
    delete DBStrm;
    mSaveDBFile = false;
    return RET_OK;
}
