#include <QThread>
#include <QDebug>
#include "tasktreepreparation.h"


TaskAMMFIMTreePreparation::TaskAMMFIMTreePreparation(TypeListTreeAMMFIM type, QObject *parent) :
    QObject(parent),
    flagStop(false),
    type(type)
{
    qDebug() << "TaskAMMFIMTreePreparation init thread ID " << QThread::currentThreadId();
}

TaskAMMFIMTreePreparation::~TaskAMMFIMTreePreparation()
{
    mtxAccess.lock();
    deleteAllModulsAMM();
    mtxAccess.unlock();
}

void TaskAMMFIMTreePreparation::slot_stopParserPreparation()
{
    flagStop = true;
}

TaskAmmFim TaskAMMFIMTreePreparation::getTaskFIMbyID(int id)
{
    mtxAccess.lock();
    for(int i = 0; i < listTasksFIM.count(); i++)
    {/*Задачи*/
        TaskAmmFim task = listTasksFIM.at(i);
        if(task.id == id)
        {
            mtxAccess.unlock();
            return task;
        }
    }
    mtxAccess.unlock();
    return TaskAmmFim();
}

TaskAmmFim TaskAMMFIMTreePreparation::getTaskAMMbyID(int id)
{
    mtxAccess.lock();
    for(int i = 0; i < listTasksAMM.count(); i++)
    {/*Задачи*/
        TaskAmmFim task = listTasksAMM.at(i);
        if(task.id == id)
        {
            mtxAccess.unlock();
            return task;
        }
    }
    mtxAccess.unlock();
    return TaskAmmFim();
}

ModuleType TaskAMMFIMTreePreparation::getTypeModuleAMMbyID(int id)
{
    ModuleType type = ModuleType::TYPE_PM;
    Module* ptrModule = nullptr;

    mtxAccess.lock();
    for(Module* module: listAllModulesAMM)
    {
        ptrModule = module->getModuleByID(id);
        if(ptrModule)
        {
            type = ptrModule->getType();
            {
                mtxAccess.unlock();
                return type;
            }
        }
    }
    mtxAccess.unlock();
    return type;
}

QTreeWidgetItem *TaskAMMFIMTreePreparation::addModuleToTreeWidgetAMM(Module *module, bool flOnlyActive, QTreeWidgetItem *parentItem)
{
    QTreeWidgetItem* itemModule = nullptr;

    if(flagStop)
        return itemModule;

    if(flOnlyActive && !module->getIsActive())
        return nullptr;

    QString text = "";
    QString ID = QString::number(module->getID());
    QString code = "";

    itemModule = new QTreeWidgetItem();
    countItems++;

    if(parentItem)
        parentItem->addChild(itemModule);

    if(module->getType() == ModuleType::TYPE_PM)
    {
        PM* PMmodul = static_cast<PM*>(module);
        text = PMmodul->getLangStructRus().title;
        code = PMmodul->pmCode();

        for(Module* module : PMmodul->getListChildModules())
        {
            addModuleToTreeWidgetAMM(module, flOnlyActive, itemModule);
        }
    }
    else
    {
        DM* DMmodul = static_cast<DM*>(module);
        text = DMmodul->getLangStructRus().techName;
        code = DMmodul->dmCode();

        //itemModule->setFlags(itemModule->flags() | Qt::ItemIsUserCheckable);
        //itemModule->setCheckState(0, Qt::Checked);
        itemModule->setIcon(0, QIcon(":/resources/icons/procedure.png"));
    }

    itemModule->setText(ColumnsTreeAMM::clmnAMM_PMorDM, text);
    itemModule->setText(ColumnsTreeAMM::clmnAMM_code, code);
    itemModule->setText(ColumnsTreeAMM::clmnAMM_ID, ID);
    itemModule->setToolTip(0, text);

    return itemModule;
}

void TaskAMMFIMTreePreparation::loadAMMtasksFromXML(QByteArray array)
{
    mtxAccess.lock();

    deleteAllModulsAMM();
    listTasksAMM.clear();

    QDomDocument docTasksDOM;

    docTasksDOM.setContent(array);

    QDomElement manifestElement = docTasksDOM.firstChildElement("manifest");
    if(manifestElement.isNull())
    {
        mtxAccess.unlock();
        return;
    }

    domElementParserAMM(manifestElement, nullptr);

    mtxAccess.unlock();
}

void TaskAMMFIMTreePreparation::loadFIMtasksFromXML(QByteArray array)
{
    mtxAccess.lock();

    listTasksFIM.clear();

    QDomDocument docTasksDOM;

    docTasksDOM.setContent(array);

    QDomElement RRJTasksElement = docTasksDOM.firstChildElement("RRJTasks");
    if(RRJTasksElement.isNull())
    {
        mtxAccess.unlock();
        return;
    }

    QDomElement taskElement = RRJTasksElement.firstChildElement();
    if(taskElement.isNull())
    {
        mtxAccess.unlock();
        return;
    }

    do
    {/*task*/

        if(flagStop)
        {
            mtxAccess.unlock();
            return;
        }

        QString name = taskElement.nodeName();
        QDomNamedNodeMap nodeMap = taskElement.attributes();

        if(name == "task")
        {
            TaskAmmFim* task = nullptr;
            task = new TaskAmmFim();

            task->initialize(/*nodeMap.namedItem("id").nodeValue().toInt()*/ TaskAmmFim::lastID++,
                             nodeMap.namedItem("type").nodeValue(),
                             nodeMap.namedItem("title").nodeValue(),
                             nodeMap.namedItem("status").nodeValue(),
                             nodeMap.namedItem("created").nodeValue(),
                             nodeMap.namedItem("changed").nodeValue());

            QDomElement malfunctionElement = taskElement.firstChildElement();
            if(!malfunctionElement.isNull())
            {
                do
                {/*malfunction*/
                    QString name = malfunctionElement.nodeName();
                    QDomNamedNodeMap nodeMap = malfunctionElement.attributes();

                    if(name == "malfunction")
                    {
                        Malfunction malfunction;

                        malfunction.initialize(nodeMap.namedItem("dmCode").nodeValue(),
                                               nodeMap.namedItem("num").nodeValue(),
                                               nodeMap.namedItem("description").nodeValue());

                        QDomElement signElement = malfunctionElement.firstChildElement();
                        if(!signElement.isNull())
                        {
                            do
                            {/*malfunctionSign*/
                                QString name = signElement.nodeName();
                                QDomNamedNodeMap nodeMap = signElement.attributes();

                                if(name == "malfunctionSign")
                                {
                                    MalfunctionSign sign;

                                    sign.initialize(nodeMap.namedItem("type").nodeValue().toInt(),
                                                    nodeMap.namedItem("description").nodeValue());

                                    malfunction.addMalfunctionSign(sign);
                                }

                            }while(! (signElement = signElement.nextSiblingElement()).isNull());
                        }
                        task->addMalfunction(malfunction);
                    }
                }while(! (malfunctionElement = malfunctionElement.nextSiblingElement()).isNull());
            }
            listTasksFIM.append(*task);
            delete task;
        }
    }while (! (taskElement = taskElement.nextSiblingElement()).isNull());

    mtxAccess.unlock();
    return;
}

void TaskAMMFIMTreePreparation::deleteAllModulsAMM()
{
    for(Module* module: listAllModulesAMM)
    {
        if(module->getType() == ModuleType::TYPE_PM)
            delete static_cast<PM*>(module);
        else
            delete static_cast<DM*>(module);
    }
    listAllModulesAMM.clear();
}

void TaskAMMFIMTreePreparation::domElementParserAMM(QDomElement element, Module* moduleParent)
{
    QString name;

    if(flagStop)
        return;

    QDomElement childElement = element.firstChildElement();
    if(childElement.isNull())
        return;

    Module* module = nullptr;

    do
    {
        name = childElement.nodeName();

       QDomNamedNodeMap nodeMap = childElement.attributes();

       if(name == "doc")
       {
           module = new PM();
       }
       else if(name == "pm")
       {
           module = new PM();
           PM* PMmodul = static_cast<PM*>(module);

           PMmodul->initialize(nodeMap.namedItem("modelIdentCode").nodeValue(),
                               nodeMap.namedItem("pmIssuer").nodeValue(),
                               nodeMap.namedItem("pmNumber").nodeValue(),
                               nodeMap.namedItem("pmVolume").nodeValue());

           if(moduleParent)
           {
               PMmodul->setParentModule(moduleParent);

               PM* PMmodulParent = static_cast<PM*>(moduleParent);
               PMmodulParent->addChildModule(module);
           }
       }
       else if(name == "dm")
       {
           module = new DM();
           DM* DMmodul = static_cast<DM*>(module);

           DMmodul->initialize(nodeMap.namedItem("modelIdentCode").nodeValue(),
                               nodeMap.namedItem("systemDiffCode").nodeValue(),
                               nodeMap.namedItem("systemCode").nodeValue(),
                               nodeMap.namedItem("subSystemCode").nodeValue(),
                               nodeMap.namedItem("subSubSystemCode").nodeValue(),
                               nodeMap.namedItem("assyCode").nodeValue(),
                               nodeMap.namedItem("disassyCode").nodeValue(),
                               nodeMap.namedItem("disassyCodeVariant").nodeValue(),
                               nodeMap.namedItem("infoCode").nodeValue(),
                               nodeMap.namedItem("infoCodeVariant").nodeValue(),
                               nodeMap.namedItem("itemLocationCode").nodeValue());

           if(moduleParent)
           {
               DMmodul->setParentModule(moduleParent);

               PM* PMmodulParent = static_cast<PM*>(moduleParent);
               PMmodulParent->addChildModule(module);
           }           
       }
       else if(name == "rus" || name == "eng")
       {
           if(moduleParent)
           {
               if(moduleParent->getType() == ModuleType::TYPE_PM)
               {//PM
                   PM* PMmodulParent = static_cast<PM*>(moduleParent);

                   if(name == "rus")
                        PMmodulParent->setLangStructRus(nodeMap.namedItem("title").nodeValue());
                   else
                        PMmodulParent->setLangStructEng(nodeMap.namedItem("title").nodeValue());
               }
               else
               {//DM
                   DM* DMmodulParent = static_cast<DM*>(moduleParent);

                   if(name == "rus")
                   {
                        DMmodulParent->setLangStructRus(nodeMap.namedItem("techName").nodeValue(),
                                                        nodeMap.namedItem("infoName").nodeValue(),
                                                        nodeMap.namedItem("pdf").nodeValue(),
                                                        nodeMap.namedItem("bookmark").nodeValue(),
                                                        nodeMap.namedItem("xml").nodeValue());

                        //Активность
                        QString canplay = nodeMap.namedItem("canplay").nodeValue();
                        if(canplay.contains("+"))
                            DMmodulParent->setIsActiveTrue();
                   }
                   else
                       DMmodulParent->setLangStructEng(nodeMap.namedItem("techName").nodeValue(),
                                                       nodeMap.namedItem("infoName").nodeValue(),
                                                       nodeMap.namedItem("pdf").nodeValue(),
                                                       nodeMap.namedItem("bookmark").nodeValue(),
                                                       nodeMap.namedItem("xml").nodeValue());
               }
           }

       }

        domElementParserAMM(childElement, module);

        if(moduleParent == nullptr)
            listAllModulesAMM.append(module);

        if(module)
            if(module->getType() == ModuleType::TYPE_DM)
            {
                TaskAmmFim* task = nullptr;
                task = new TaskAmmFim();
                task->setID(module->getID());
                task->ammProcedure.title = static_cast<DM*>(module)->getLangStructRus().techName;
                task->ammProcedure.dmCode = static_cast<DM*>(module)->dmCode();

                listTasksAMM.append(*task);
                delete task;
            }

    }while (! (childElement = childElement.nextSiblingElement()).isNull());
}

void TaskAMMFIMTreePreparation::slot_prepareAMMListItems(QByteArray array, bool flOnlyActive, bool flRequestFirst)
{
    qDebug() << "TaskAMMFIMTreePreparation::slot_prepareAMMListItems thread ID " << QThread::currentThreadId();

    if(flRequestFirst)
    {
        loadAMMtasksFromXML(array);
    }

    if(flOnlyActive)
    {
        listItemsOnlyActive.clear();

        for(Module* module : listAllModulesAMM)
        {
            QTreeWidgetItem*  item = addModuleToTreeWidgetAMM(module, true);
            listItemsOnlyActive.append(item);
        }

        emit signal_listAMMItemsReady(listItemsOnlyActive);
    }
    else
    {
        listItemsAll.clear();

        for(Module* module : listAllModulesAMM)
        {
            QTreeWidgetItem*  item = addModuleToTreeWidgetAMM(module, false);
            listItemsAll.append(item);
        }

        emit signal_listAMMItemsReady(listItemsAll);
    }
}

void TaskAMMFIMTreePreparation::slot_prepareAMMListItemsForTrainee(QList<TaskAmmFim> listTasks)
{
    qDebug() << "TaskAMMFIMTreePreparation::slot_prepareAMMListItemsForTrainee thread ID " << QThread::currentThreadId();

    listItemsAll.clear();

    mtxAccess.lock();

    this->listTasksAMM = listTasks;

    for(TaskAmmFim task : listTasks)
    {
        QTreeWidgetItem* item = nullptr;

        QString text = task.ammProcedure.title;
        QString ID = QString::number(task.getID());
        QString code = task.ammProcedure.dmCode;
        QString status = task.status;

        item = new QTreeWidgetItem();
        item->setIcon(0, QIcon(":/resources/icons/procedure.png"));

        item->setText(ColumnsTreeAMM::clmnAMM_PMorDM, text);
        item->setText(ColumnsTreeAMM::clmnAMM_code, code);
        item->setText(ColumnsTreeAMM::clmnAMM_ID, ID);

        if(status == "completed")
        {
            item->setText(ColumnsTreeAMM::clmnAMM_status, tr("completed"));
            item->setIcon(ColumnsTreeAMM::clmnAMM_status, QIcon(QStringLiteral(":/resources/icons/circleGreen.png")));
        }
        else if(status == "failed")
        {
            item->setText(ColumnsTreeAMM::clmnAMM_status, tr("failed"));
            item->setIcon(ColumnsTreeAMM::clmnAMM_status, QIcon(QStringLiteral(":/resources/icons/circleRed.png")));
        }
        else if(status == "checkup")
        {
            item->setText(ColumnsTreeAMM::clmnAMM_status, tr("checkup"));
            item->setIcon(ColumnsTreeAMM::clmnAMM_status, QIcon(QStringLiteral(":/resources/icons/circleYellow.png")));
        }
        else
        {
            item->setText(ColumnsTreeAMM::clmnAMM_status, tr("new"));
            item->setIcon(ColumnsTreeAMM::clmnAMM_status, QIcon(QStringLiteral(":/resources/icons/circleGray.png")));
        }

        item->setToolTip(0, text);

        listItemsAll.append(item);
    }

    mtxAccess.unlock();

    Q_EMIT signal_listAMMItemsReady(listItemsAll);
}

void TaskAMMFIMTreePreparation::slot_prepareFIMListItems(QByteArray array)
{
    qDebug() << "TaskAMMFIMTreePreparation::slot_prepareFIMListItems thread ID " << QThread::currentThreadId();

    loadFIMtasksFromXML(array);

    listItemsAll.clear();

    mtxAccess.lock();

    for(TaskAmmFim taskPtr : listTasksFIM)
        {/*Задачи*/
            TaskAmmFim task = taskPtr;

            QTreeWidgetItem* itemTask = new QTreeWidgetItem();

            itemTask->setText(0, task.title);
            itemTask->setText(1, QString::number(task.id));
            //itemTask->setFlags(itemTask->flags() | Qt::ItemIsUserCheckable);
            //itemTask->setCheckState(0, Qt::Checked);

            if(task.status == "completed")
            {
                itemTask->setText(2, tr("completed"));
                itemTask->setIcon(2, QIcon(QStringLiteral(":/resources/icons/circleGreen.png")));
            }
            else if(task.status == "failed")
            {
                itemTask->setText(2, tr("failed"));
                itemTask->setIcon(2, QIcon(QStringLiteral(":/resources/icons/circleRed.png")));
            }
            else if(task.status == "checkup")
            {
                itemTask->setText(2, tr("checkup"));
                itemTask->setIcon(2, QIcon(QStringLiteral(":/resources/icons/circleYellow.png")));
            }
            else
            {
                itemTask->setText(2, tr("new"));
                itemTask->setIcon(2, QIcon(QStringLiteral(":/resources/icons/circleGray.png")));
            }


            itemTask->setIcon(0, QIcon(":/resources/icons/procedure.png"));
            itemTask->setToolTip(0, task.title);


            for (int j = 0; j < task.malfunctionList.count(); j++)
            {/*Неисправности*/
                Malfunction malfunction = task.malfunctionList.at(j);

                QTreeWidgetItem* itemMalfunction = new QTreeWidgetItem();

                itemMalfunction->setText(0, malfunction.description);
                if(type == TypeListTreeAMMFIM::listCommon)
                {
                    itemMalfunction->setFlags(itemMalfunction->flags() | Qt::ItemIsUserCheckable);
                    itemMalfunction->setCheckState(0, Qt::Checked);
                }

                itemMalfunction->setIcon(0, QIcon(":/resources/icons/malfunction.png"));
                itemMalfunction->setToolTip(0, malfunction.description);

                itemTask->addChild(itemMalfunction);

                for (int k = 0; k < malfunction.malfunctionSigns.count(); k++)
                {/*Сигнализация*/
                    MalfunctionSign sign = malfunction.malfunctionSigns.at(k);

                    QTreeWidgetItem* itemSign = new QTreeWidgetItem();

                    itemSign->setText(0, sign.description);
                    //itemSign->setFlags(itemSign->flags() | Qt::ItemIsUserCheckable);
                    //itemSign->setCheckState(0, Qt::Checked);
                    itemSign->setIcon(0, QIcon(":/resources/icons/sign.png"));
                    itemSign->setToolTip(0, sign.description);

                    itemMalfunction->addChild(itemSign);
                }
            }
            listItemsAll.append(itemTask);
        }

    mtxAccess.unlock();

    Q_EMIT signal_listFIMItemsReady(listItemsAll);
}

void TaskAMMFIMTreePreparation::slot_prepareFIMListItemsForTrainee(QList<TaskAmmFim> listTasks)
{
    qDebug() << "TaskAMMFIMTreePreparation::slot_prepareFIMListItemsForTrainee thread ID " << QThread::currentThreadId();

    listItemsAll.clear();

    mtxAccess.lock();
    this->listTasksFIM = listTasks;

    for(TaskAmmFim task : listTasks)
    {/*Задачи*/
        //TaskAmmFim* task = listTaskAmmFim.at(i);
        //TaskAmmFim* taskNew = nullptr;
        //taskNew = new TaskAmmFim();
        //*taskNew = task;
        //listTaskFIM.append(taskNew);

        QTreeWidgetItem* itemTask = new QTreeWidgetItem();

        itemTask->setText(0, task.title);
        itemTask->setText(1, QString::number(task.id));
        //itemTask->setFlags(itemTask->flags() | Qt::ItemIsUserCheckable);
        //itemTask->setCheckState(0, Qt::Checked);

        if(task.status == "completed")
        {
            itemTask->setText(2, tr("completed"));
            itemTask->setIcon(2, QIcon(QStringLiteral(":/resources/icons/circleGreen.png")));
        }
        else if(task.status == "failed")
        {
            itemTask->setText(2, tr("failed"));
            itemTask->setIcon(2, QIcon(QStringLiteral(":/resources/icons/circleRed.png")));
        }
        else if(task.status == "checkup")
        {
            itemTask->setText(2, tr("checkup"));
            itemTask->setIcon(2, QIcon(QStringLiteral(":/resources/icons/circleYellow.png")));
        }
        else
        {
            itemTask->setText(2, tr("new"));
            itemTask->setIcon(2, QIcon(QStringLiteral(":/resources/icons/circleGray.png")));
        }


        itemTask->setIcon(0, QIcon(":/resources/icons/procedure.png"));
        itemTask->setToolTip(0, task.title);


        for (int j = 0; j < task.malfunctionList.count(); j++)
        {/*Неисправности*/
            Malfunction malfunction = task.malfunctionList.at(j);

            QTreeWidgetItem* itemMalfunction = new QTreeWidgetItem();

            itemMalfunction->setText(0, malfunction.description);
            if(type == TypeListTreeAMMFIM::listCommon)
            {
                itemMalfunction->setFlags(itemMalfunction->flags() | Qt::ItemIsUserCheckable);
                itemMalfunction->setCheckState(0, Qt::Checked);
            }

            itemMalfunction->setIcon(0, QIcon(":/resources/icons/malfunction.png"));
            itemMalfunction->setToolTip(0, malfunction.description);

            itemTask->addChild(itemMalfunction);

            for (int k = 0; k < malfunction.malfunctionSigns.count(); k++)
            {/*Сигнализация*/
                MalfunctionSign sign = malfunction.malfunctionSigns.at(k);

                QTreeWidgetItem* itemSign = new QTreeWidgetItem();

                itemSign->setText(0, sign.description);
                //itemSign->setFlags(itemSign->flags() | Qt::ItemIsUserCheckable);
                //itemSign->setCheckState(0, Qt::Checked);
                itemSign->setIcon(0, QIcon(":/resources/icons/sign.png"));
                itemSign->setToolTip(0, sign.description);

                itemMalfunction->addChild(itemSign);
            }
        }

        listItemsAll.append(itemTask);
    }

    mtxAccess.unlock();

    Q_EMIT signal_listFIMItemsReady(listItemsAll);
}
