#include "maincontrol.h"
#include "readmodulefromredis.h"
#include <QJsonArray>
#include <QJsonObject>
#include <QJsonDocument>
#include <fstream>
#include <QtCore/QVariant>
#include <QtCore/QDebug>
#include <QtWidgets/QApplication>

std::string loadContent(std::string szFilename)
{
    szFilename = QString::fromLocal8Bit(szFilename.c_str()).toLocal8Bit().toStdString();
    std::ifstream inStream(szFilename.c_str(),std::ios::in | std::ios::binary);
    if( inStream.is_open() != true )
    {
        return "";
    }

    return std::string((std::istreambuf_iterator<char>(inStream)),std::istreambuf_iterator<char>());
}

maincontrol::maincontrol() : QObject()
{
    m_pRedis = nullptr;
    m_pTDengine = nullptr;
    m_mpItems.clear();
}

void maincontrol::OnData(std::string name,QVariant val)
{
    // 传出来的设备命令需要发送给redis（module->oneitem->maincontrol）
    //m_pRedis->hset("devicecommand",name.c_str(),val.toString());
    m_pRedis->Publish(name,val);
}

void maincontrol::sltSubData(const std::string topic, const std::string msg)
{
    // td过来的数据往模块里发, maincontrol->oneitem->module
    std::multimap<std::string,oneitem*>::iterator it = this->m_mpItems.find(topic);
    if(it != this->m_mpItems.end())
    {
        //找到了
        //输出multimap 中的同一键的多个值
        //方法一 通过比较key ,循环判断   推荐使用
        for(; it != this->m_mpItems.end(); it++)
        {
            if((*it).first == topic)
            {
                (*it).second->OnSubData(topic,msg);
            }
            else
            {
                break;
            }
        }
    }
}

void maincontrol::loadConfig(std::string szFile,std::map<QString,QString>& mps)
{
    std::string cfg = loadContent(szFile);
    QJsonDocument jsonDoc(QJsonDocument::fromJson(cfg.c_str()));
    QJsonObject json = jsonDoc.object();
    QStringList keys = json.keys();
    foreach (QString item, keys)
    {
        mps[item] = json[item].toString();
    }
}

void maincontrol::Startup()
{
    // merge file name
    QString szWorkDir = qApp->applicationDirPath();
    if( szWorkDir.right(1).contains("/") == false && szWorkDir.right(1).contains("\\") == false)
    {
        szWorkDir += "/";
    }
    std::string szFile = szWorkDir.toLocal8Bit().toStdString() + "config/server.json";

    // load server config
    std::map<std::string,tagSetup> mpConfig;
    std::string cfg = loadContent(szFile);
    QJsonDocument jsonDoc(QJsonDocument::fromJson(cfg.c_str()));
    QJsonArray ja = jsonDoc.array();
    for(auto i : ja)
    {
        QJsonObject json = i.toObject();
        QStringList items = json.keys();
        if( items.contains("ignore",Qt::CaseInsensitive) && json["ignore"].type() == QJsonValue::Bool && json["ignore"].toBool())
        {
            continue;
        }

        tagSetup ts;
        ts.addr = json["addr"].toString().toLocal8Bit().toStdString();
        ts.user = json["user"].toString().toLocal8Bit().toStdString();
        ts.password = json["password"].toString().toLocal8Bit().toStdString();
        ts.db = json["database"].toString().toLocal8Bit().toStdString();
        ts.port = json["port"].toInt();

        std::string szName = json["name"].toString().toLocal8Bit().toStdString();
        mpConfig[szName] = ts;
    }

    m_pRedis = new RedisAgent();
    m_pRedis->Connect(mpConfig["redis"]);           // redis

    m_pTDengine = new TDAgent();
    m_pTDengine->Connect(mpConfig["tdengine"]);     // td

    // server.id
    std::map<QString,QString> mps;
    this->loadConfig(szWorkDir.toLocal8Bit().toStdString() + "config/lpintelligentcontrol.json",mps);

    // 从redis里找到所有的智能控制实例（当前服务器管理的）
    readmodulefromredis instance(m_pRedis);
    std::list<ModuleInfo> modules = instance.loadModules(mps["serverid"]);
    std::list<ModuleInfo>::iterator itr;
    for( itr = modules.begin();itr!= modules.end();++itr)
    {
        ModuleInfo moduleInfo = *itr;
        oneitem *poneitem = new oneitem();
        poneitem->regConsumer(this);
        poneitem->createmodule(moduleInfo);
        m_pTDengine->Subscribe(moduleInfo.lstInputs);
        std::list<std::string>::iterator itrI;
        for( itrI = moduleInfo.lstInputs.begin(); itrI != moduleInfo.lstInputs.end(); ++itrI )
        {
            this->m_mpItems.insert(std::pair<std::string,oneitem*>((*itrI), poneitem));
        }
    }
    qRegisterMetaType<std::string>("std::string");
    connect(m_pTDengine,SIGNAL(sigEvent(const std::string, const std::string)),this,SLOT(sltSubData(const std::string, const std::string)));
}
