#include "workspace/WorkSpaceXMLParse.h"

#include "workspace/WorkSpace.h"
#include "entities/EntitiesManager.h"

#include "common/SpdLogger.h"
#include "workspace/WorkSpaceManager.h"
#include "utils/StringUtils.h"

WorkSpaceXMLParse::WorkSpaceXMLParse(WorkSpace* workspace, QObject* parent) noexcept
    : QObject(parent)
    , workSpace_(workspace) {
}

bool WorkSpaceXMLParse::Save(const QString& path) {
    path_ = path;
    return false;
}

bool WorkSpaceXMLParse::ParseScene(const tinyxml2::XMLElement* element) {
    if (nullptr == element) {
        LOG_WARN("element is nullptr");
        return false;
    }

    const tinyxml2::XMLAttribute* current = element->FirstAttribute();
    bool flag = false;
    while (nullptr != current) {
        const char* eleName = current->Name();
        if (0 == strcmp(eleName, "name")) {
            const char* name = current->Value();

            workSpace_->SetName(name);
            flag = true;
            
        } else if (0 == strcmp(eleName, "describe")) {
            const char* value = current->Value();

            workSpace_->SetDescribe(value);
            flag = true;
        } else if (0 == strcmp(eleName, "uuid")) {
            const char* value = current->Value();

            workSpace_->SetUUid(value);
            flag = true;
        } else if (0 == strcmp(eleName, "viewpoint")) {
            const char* value = current->Value();
            workSpace_->SetHomeViewpoint(StringUtils::StringToViewpoint("home", value));
            flag = true;
        }
        current = current->Next();
    }
    
    return flag;
}

bool WorkSpaceXMLParse::ParseTimestep(const tinyxml2::XMLElement* element) {
    if (nullptr == element) {
        LOG_WARN("element is nullptr");
        return false;
    }

    const char* path = element->Attribute("path");
    if (nullptr == path) {
        LOG_WARN("element not has path");
        return false;
    }
    
    return workSpace_->SetTimestepPath(path);
}

bool WorkSpaceXMLParse::ParseLamp(const tinyxml2::XMLElement* element) {
    if (nullptr == element) {
        LOG_WARN("element is nullptr");
        return false;
    }

    const char* path = element->Attribute("path");
    if (nullptr == path) {
        LOG_WARN("element not has path");
        return false;
    }

    return workSpace_->SetLampPath(path);
}

bool WorkSpaceXMLParse::ParseEntities(const tinyxml2::XMLElement* element) {
    if (nullptr == element) {
        LOG_WARN("element is nullptr");
        return false;
    }

    const char* eleName = element->Name();
    if (0 == strcmp(eleName, "entities")) {
        return EntitiesManager::Get().Parse(element, workSpace_);
    }
    LOG_WARN("element not has entities");
    return false;
}

bool WorkSpaceXMLParse::ParseChart(const tinyxml2::XMLElement* element)
{
    if (nullptr == element) {
        LOG_WARN("element is nullptr");
        return false;
    }

    const tinyxml2::XMLElement* xmlElement = element->FirstChildElement();
    while (nullptr != xmlElement) {
        const char* name = xmlElement->Name();
        if (0 == strcmp(name, "Wave"))
        {
            QVariantMap varChart;
            const tinyxml2::XMLAttribute* attribute = xmlElement->FirstAttribute();
            while (nullptr != attribute) {

                WorkSpaceManager::Get().SetDYTWaveFile(QString::fromLocal8Bit(attribute->Value()));
                attribute = attribute->Next();
            }
        }
        else if (0 == strcmp(name, "Report"))
        {
            QVariantMap varChart;
            const tinyxml2::XMLAttribute* attribute = xmlElement->FirstAttribute();
            while (nullptr != attribute) {

                WorkSpaceManager::Get().SetDYTReportFile(QString::fromLocal8Bit(attribute->Value()));
                attribute = attribute->Next();
            }
        }
        else if (0 == strcmp(name, "RD"))
        {
            QVariantMap varChart;
            const tinyxml2::XMLAttribute* attribute = xmlElement->FirstAttribute();
            while (nullptr != attribute) {

                WorkSpaceManager::Get().SetDYTRDFile(QString::fromLocal8Bit(attribute->Value()));
                attribute = attribute->Next();
            }
        }
        else if (0 == strcmp(name, "MMain"))
        {
            QVariantMap varChart;
            const tinyxml2::XMLAttribute* attribute = xmlElement->FirstAttribute();
            while (nullptr != attribute) {

                WorkSpaceManager::Get().SetDYTMMainFile(QString::fromLocal8Bit(attribute->Value()));
                attribute = attribute->Next();
            }
        }
        else if (0 == strcmp(name, "MLD"))
        {
            QVariantMap varChart;
            const tinyxml2::XMLAttribute* attribute = xmlElement->FirstAttribute();
            while (nullptr != attribute) {

                WorkSpaceManager::Get().SetDYTMLDFile(QString::fromLocal8Bit(attribute->Value()));
                attribute = attribute->Next();
            }
        }
        else if (0 == strcmp(name, "MSeekerSim"))
        {
            QVariantMap varChart;
            const tinyxml2::XMLAttribute* attribute = xmlElement->FirstAttribute();
            while (nullptr != attribute) {

                WorkSpaceManager::Get().SetDYTMSeekerSimFile(QString::fromLocal8Bit(attribute->Value()));
                attribute = attribute->Next();
            }
        }
        else if (0 == strcmp(name, "MatlabP"))
        {
            QVariantMap varChart;
            const tinyxml2::XMLAttribute* attribute = xmlElement->FirstAttribute();
            while (nullptr != attribute) {

                WorkSpaceManager::Get().SetDYTMatlabPFile(QString::fromLocal8Bit(attribute->Value()));
                attribute = attribute->Next();
            }
        }

        xmlElement = xmlElement->NextSiblingElement();
    }

    return true;
}

bool WorkSpaceXMLParse::ParseReport(const tinyxml2::XMLElement* element)
{
    QString strFile = "";
    int iBatch = 0;

    const tinyxml2::XMLAttribute* attribute = element->FirstAttribute();
    while (nullptr != attribute) {
        if (0 == strcmp(attribute->Name(), "file"))
        {
            strFile = QString::fromLocal8Bit(attribute->Value());
        }
        else if (0 == strcmp(attribute->Name(), "batch"))
        {
            iBatch = atoi(attribute->Value());
        }

        attribute = attribute->Next();
    }

    return true;
}

bool WorkSpaceXMLParse::Load(const QString& dyt) {
    std::string path = dyt.toStdString();
    LOG_INFO("load path:{}", path);
    tinyxml2::XMLDocument xmlDocument;
    tinyxml2::XMLError error = xmlDocument.LoadFile(path.c_str());
    if (tinyxml2::XMLError::XML_SUCCESS != error) {
        LOG_INFO("load feiled:{}", static_cast<int>(error));
        return false;
    }

    const tinyxml2::XMLElement* root = xmlDocument.RootElement();
    if (!ParseScene(root)) {
        return false;
    }

    const tinyxml2::XMLElement* xmlElement = root->FirstChildElement();
    while (nullptr != xmlElement) {
        const char* name = xmlElement->Name();
        if (0 == strcmp(name, "entities")) {
            ParseEntities(xmlElement);
        } else if (0 == strcmp(name, "timestep")) {
            ParseTimestep(xmlElement);
        } else if (0 == strcmp(name, "lamp")) {
            ParseLamp(xmlElement);
        }
        else if (0 == strcmp(name, "charts")) {
            ParseChart(xmlElement);
        }
        else if (0 == strcmp(name, "ReportInfo")) {
            ParseReport(xmlElement);
        }
        xmlElement = xmlElement->NextSiblingElement();
    }

    return true;
}