#include "Standard.h"
#include <QDebug>
#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>
#include <QByteArray>
#include <QFile>

//#define JSON_FILE_NAME "standards"
//#define JSON_FILE_TAG "STANDARDS_JLWL"

#define JSON_FILE_VERSION "V1.0"

static StandardManager* _standardmanager = nullptr;

StandardManager::StandardManager(QObject* parent)
    :QObject(parent)
{

}

StandardManager::~StandardManager(){

}

StandardManager* StandardManager::instance(){
    if(nullptr == _standardmanager){
        _standardmanager = new StandardManager();
    }

    return _standardmanager;
}

void StandardManager::add_GB()
{
    Standard std;
    std.standard_name = "国标";
    std.positive_target = 4.5;
    std.negative_target = -1.5;
    std.interval_time = 300;

    std.item_count = 4;
    std.item[0].oilcompartment_volume = 9500;
    std.item[0].system_threshold = 0.25;
    std.item[0].valve_threshold = 1.30;

    std.item[1].oilcompartment_volume = 5500;
    std.item[1].system_threshold = 0.38;
    std.item[1].valve_threshold = 1.30;

    std.item[2].oilcompartment_volume = 3800;
    std.item[2].system_threshold = 0.50;
    std.item[2].valve_threshold = 1.30;

    std.item[3].oilcompartment_volume = 0;
    std.item[3].system_threshold = 0.65;
    std.item[3].valve_threshold = 1.30;

    m_standard.push_back(std);
}

void StandardManager::load_standards()
{
    QFile file("./standards.json");
    if(!file.open(QIODevice::ReadOnly|QIODevice::Text)){
        //QJsonObject jsonObject;
        //jsonObject["name"] =""
        qDebug() << "load_standards file open failed ";
        return ;
    }

    QTextStream jsonstream(&file);

    jsonstream.setCodec("UTF-8");

    //jsonstream.readAll();
    qDebug() << "load_standards enter";

    QString jsonString = jsonstream.readAll();
    file.close();


    QJsonParseError json_error;
    QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonString.toUtf8(), &json_error);
    if(json_error.error == QJsonParseError::NoError){
        QJsonObject rootObj = jsonDoc.object();
        QJsonArray  jsonArray;
        QString str;

        qDebug() << "load_standards enter 22222222";

        if(rootObj.contains("version") && rootObj.value("version").isString()){
            str = rootObj.value("version").toString();
            //qDebug() <<  str ;
            if(str != JSON_FILE_VERSION){
                qDebug() <<  str << " not equal:" << JSON_FILE_VERSION;
               return;
            }
        }

        if(rootObj.contains("standards") && rootObj.value("standards").isArray()){
            jsonArray = rootObj.value("standards").toArray();
            for(int i=0; i < jsonArray.size(); i++){

                Standard std;
                std.item_count = 0;
                QJsonObject childObj = jsonArray[i].toObject();
                if(childObj.contains("name") && childObj.value("name").isString()){
                    std.standard_name = childObj.value("name").toString();
                }

                if(childObj.contains("pt_v") && childObj.value("pt_v").isDouble()){
                    std.positive_target = childObj.value("pt_v").toDouble();
                }


                if(childObj.contains("nt_v") && childObj.value("nt_v").isDouble()){
                    std.negative_target = childObj.value("nt_v").toDouble();
                }

                if(childObj.contains("intervals") && childObj.value("intervals").isDouble()){
                    std.interval_time = childObj.value("intervals").toInt();
                }

                if(childObj.contains("items") && childObj.value("items").isArray()){
                    QJsonArray  jsonArray_i;
                    jsonArray_i = childObj.value("items").toArray();
                    std.item_count = jsonArray_i.size();

                    if(std.item_count > 4){
                       std.item_count = 4;
                    }

                    qDebug() << "item_count:" << std.item_count;

                    for(int j =0 ; j<std.item_count; j++){
                        QJsonObject itemObj = jsonArray_i[j].toObject();

                        if(itemObj.contains("volume") && itemObj.value("volume").isDouble()){
                            std.item[j].oilcompartment_volume = itemObj.value("volume").toInt();
                        }

                        if(itemObj.contains("s_threshold") && itemObj.value("s_threshold").isDouble()){
                            std.item[j].system_threshold = itemObj.value("s_threshold").toDouble();
                        }

                        if(itemObj.contains("v_threshold") && itemObj.value("v_threshold").isDouble()){
                            std.item[j].valve_threshold = itemObj.value("v_threshold").toDouble();
                        }

                    }
                }

                if(true != std.standard_name.isEmpty() && std.item_count > 0){
                    m_standard.push_back(std);
                     qDebug() << " m_standard.push_back(std)" ;
                }
            }
        }


    }else{
        qDebug() << "json_error.error occurred";
    }

}

void StandardManager::save_standards()
{
    QJsonArray stdArray;
    //QJsonArray itemArray;
    QJsonObject rootObj;

    rootObj.insert("version", JSON_FILE_VERSION);

    for(int i=0; i < static_cast<int>(m_standard.size()); i++){

        QJsonObject stdObj;
        QJsonArray itemArray;

        stdObj.insert("name", m_standard[i].standard_name);

        stdObj.insert("pt_v", m_standard[i].positive_target);
        stdObj.insert("nt_v", m_standard[i].negative_target);
        stdObj.insert("intervals", m_standard[i].interval_time);

       for(int j=0; j < m_standard[i].item_count; j++){
           QJsonObject itemObj;
           itemObj.insert("volume", m_standard[i].item[j].oilcompartment_volume);
           itemObj.insert("s_threshold", m_standard[i].item[j].system_threshold);
           itemObj.insert("v_threshold", m_standard[i].item[j].valve_threshold);

           itemArray.append(itemObj);
       }

       stdObj.insert("items", itemArray);
       stdArray.append(stdObj);
    }

    rootObj.insert("standards", stdArray);

    QJsonDocument jsonDoc;
    jsonDoc.setObject(rootObj);

    QByteArray byteArray = jsonDoc.toJson(QJsonDocument::Indented);
    QFile file("./standards.json");
    if(!file.open(QIODevice::WriteOnly | QIODevice::Text))
    {
        qDebug() << QString("fail to open the file: %1, %2, %3").arg(__FILE__).arg(__LINE__).arg(__FUNCTION__);
        return;
    }
    QTextStream out(&file);
    out.setCodec("UTF-8");
    out << byteArray;
    file.close();

    qDebug() << QString("save standards ok : %1, %2, %3").arg(__FILE__).arg(__LINE__).arg(__FUNCTION__);

}

void StandardManager::init()
{
    m_standard.clear();

    qDebug()<< QString("init enter : %1, %2, %3").arg(__FILE__).arg(__LINE__).arg(__FUNCTION__);
    load_standards();

    //check GB
    QString gb_name = "国标";
    bool gb_inside = false;

    for(int i=0; i < static_cast<int>(m_standard.size()); i++){
       if(gb_name == m_standard[i].standard_name){
           gb_inside =  true;
       }
    }

    if(false == gb_inside){
        add_GB();
    }
}


QJsonObject StandardManager::get_names()
{
    QJsonObject jsonObj;
    QJsonArray nameArray;

    //int num = static_cast<int>m_standard.size();

    jsonObj.insert("num", static_cast<int>(m_standard.size()));

    for(int i=0; i < static_cast<int>(m_standard.size()); i++){
        nameArray.append(m_standard[i].standard_name);
    }

    jsonObj.insert("names", nameArray);

    return jsonObj;
}

QJsonObject StandardManager::get_standard(const QString name)
{
    QJsonObject stdObj;

    for(int i=0; i < static_cast<int>(m_standard.size()); i++){
        if(name == m_standard[i].standard_name){

            stdObj.insert("name", m_standard[i].standard_name);
            stdObj.insert("ptv", m_standard[i].positive_target);
            stdObj.insert("ntv", m_standard[i].negative_target);
            stdObj.insert("intervals", m_standard[i].interval_time);

            stdObj.insert("count", m_standard[i].item_count);
            QJsonArray itemArray;

            for(int j=0; j < m_standard[i].item_count; j++){
                QJsonObject itemObj;
                itemObj.insert("volume", m_standard[i].item[j].oilcompartment_volume);
                itemObj.insert("s_threshold", m_standard[i].item[j].system_threshold);
                itemObj.insert("v_threshold", m_standard[i].item[j].valve_threshold);

                itemArray.append(itemObj);
            }

            stdObj.insert("item", itemArray);
            break;
        }
    }


    return stdObj;

}

void StandardManager::remove_standard(const QString name)
{
    bool bExist = false;
    for(int i=0; i < static_cast<int>(m_standard.size()); i++){
        if(name == m_standard[i].standard_name){
            bExist = true;
            m_standard.erase(m_standard.begin()+i);
            break;
        }
    }

    if(true == bExist){
        save_standards();
    }

}

bool StandardManager::add_standard(const QString& jsonStr )
{
    bool bExist = false;
    Standard std;

    qDebug() << jsonStr;

    QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonStr.toUtf8());
    QJsonObject jsonObj = jsonDoc.object();

    std.item_count = 0;
    //QJsonObject childObj = jsonArray[i].toObject();

    if(jsonObj.contains("name") && jsonObj.value("name").isString()){
        std.standard_name = jsonObj.value("name").toString();
    }else{
        qDebug() << "add_standard no name";
        return false;
    }

    if(jsonObj.contains("ptv") && jsonObj.value("ptv").isDouble()){
        std.positive_target = jsonObj.value("ptv").toDouble();
    }else{
        qDebug() << "add_standard no ptv";
        return false;
    }

    if(jsonObj.contains("ntv") && jsonObj.value("ntv").isDouble()){
        std.negative_target = jsonObj.value("ntv").toDouble();
    }else{
        qDebug() << "add_standard no ntv";
        return false;
    }

    if(jsonObj.contains("intervals") && jsonObj.value("intervals").isDouble()){
        std.interval_time = jsonObj.value("intervals").toInt();
    }else{
        qDebug() << "add_standard no ntv";
        return false;
    }

    if(jsonObj.contains("count") && jsonObj.value("count").isDouble()){
        std.item_count = jsonObj.value("count").toInt();
    }else{
        qDebug() << "add_standard no count";
        return false;
    }

    if(jsonObj.contains("item") && jsonObj.value("item").isArray()){
        QJsonArray  jsonArray_i;
        jsonArray_i = jsonObj.value("item").toArray();

        if(std.item_count > 4){
           std.item_count = 4;
        }

        for(int j =0 ; j<std.item_count; j++){
            QJsonObject itemObj = jsonArray_i[j].toObject();

            if(itemObj.contains("volume") && itemObj.value("volume").isDouble()){
                std.item[j].oilcompartment_volume = itemObj.value("volume").toInt();
            }

            if(itemObj.contains("s_threshold") && itemObj.value("s_threshold").isDouble()){
                std.item[j].system_threshold = itemObj.value("s_threshold").toDouble();
            }

            if(itemObj.contains("v_threshold") && itemObj.value("v_threshold").isDouble()){
                std.item[j].valve_threshold = itemObj.value("v_threshold").toDouble();
            }

        }


    }else{
        qDebug() << "add_standard no item";
        return false;
    }

    //check standard is exist?
    for(int i=0; i < static_cast<int>(m_standard.size()); i++){
        if(std.standard_name == m_standard[i].standard_name){
            bExist = true;

            m_standard[i].positive_target = std.positive_target;
            m_standard[i].negative_target = std.negative_target;
            m_standard[i].interval_time = std.interval_time;

            m_standard[i].item_count = std.item_count;
            for(int j=0; j< std.item_count; j++){
                m_standard[i].item[j].oilcompartment_volume = std.item[j].oilcompartment_volume;
                m_standard[i].item[j].system_threshold = std.item[j].system_threshold;
                m_standard[i].item[j].valve_threshold = std.item[j].valve_threshold;
            }

        }
    }

    if(false == bExist){
        m_standard.push_back(std);
    }

    save_standards();
    qDebug() << "add_standard ok";

    return true;
}


bool StandardManager::getStandard(const QString& name, Standard& standard)
{

    for(int i=0; i < static_cast<int>(m_standard.size()); i++){
        if(name == m_standard[i].standard_name){
            standard = m_standard.at(i);
            return true;
        }
    }

     return false;
}
