#include "mynetmanager.h"
#include <QUrl>
#include <QByteArray>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QEventLoop>
#include <iostream>
#include <QDebug>
#include <QFile>
#include <QTextStream>
#include <QIODevice>
#include <QIODevice>
#include <QDataStream>
#include <QTimer>
#include <QDir>

using namespace std;

MyNetManager::MyNetManager(QObject *parent): QObject(parent){
    m_pManager = new QNetworkAccessManager(this);

    keep = nullptr;
    keepNetState = NET_DISCONNECT;
    keepTimer = new QTimer(this);

    connect(m_pManager, &QNetworkAccessManager::finished,this,
            &MyNetManager::onKeepConnectFinished);

}
MyNetManager::~MyNetManager()
{

}

void MyNetManager::SetIp(QString ip)
{
    qDebug() << QString("SetIp : %1\n").arg(ip);
    this->ip = ip;
}

bool MyNetManager::SetTempraturePara(uint16_t reflectiveTemperature, float emissivity, uint16_t distance)
{
    char buff[1024];
    qDebug() << QString("SetTempraturePara : reflectiveTemperature:%1, emissivity:%2, distance:%3\n")
                .arg(reflectiveTemperature).arg(emissivity).arg(distance);
    sprintf(buff, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\
            <PixelToPixelParam version=\"2.0\" xmlns=\"http://www.hikvision.com/ver20/XMLSchema\">\
            <id>2</id>\
            <maxFrameRate>400</maxFrameRate>\
            <reflectiveEnable>false</reflectiveEnable>\
            <reflectiveTemperature>%d</reflectiveTemperature>\
            <emissivity>%f</emissivity>\
            <distance>%d</distance>\
            <refreshInterval>80</refreshInterval>\
            <distanceUnit>centimeter</distanceUnit>\
            <temperatureDataLength>4</temperatureDataLength>\
            <JpegPictureWithAppendData>\
            <jpegPicEnabled>true</jpegPicEnabled>\
            <visiblePicEnabled>true</visiblePicEnabled>\
            <rulesOverlayEnable>false</rulesOverlayEnable>\
            <visiblePicResolution>800*600</visiblePicResolution>\
            <thermalPicResolution>160*120</thermalPicResolution>\
            </JpegPictureWithAppendData>\
            </PixelToPixelParam>",
            reflectiveTemperature,emissivity,distance);
    QByteArray array = QByteArray(buff);

    bool rtn =  putWait(ip + "/ISAPI/Thermal/channels/2/thermometry/pixelToPixelParam", array);

    qDebug()<< "SetTempraturePara rtn =" << rtn << endl;
    return rtn;
}

bool MyNetManager::SetAlarmPara(uint16_t alert, uint16_t alarm, uint16_t alarm_time)
{
    char buff[4096];
    qDebug() << QString("SetAlarmPara : alarm:%1, emissivity:%2, alarm_time:%3\n")
                .arg(alert).arg(alarm).arg(alarm_time);
    sprintf(buff, R"(<?xml version="1.0" encoding="UTF-8"?>
                       <ThermometryBasicParam version="2.0" xmlns="http://www.hikvision.com/ver20/XMLSchema">
                       <id>2</id>
                       <enabled>true</enabled>
                       <streamOverlay>true</streamOverlay>
                       <pictureOverlay>false</pictureOverlay>
                       <temperatureRange>0~550</temperatureRange>
                       <temperatureUnit>degreeCentigrade</temperatureUnit>
                       <emissivity>0.95</emissivity>
                       <distanceUnit>centimeter</distanceUnit>
                       <specialPointThermType>centerPoint</specialPointThermType>
                       <distance>20</distance>
                       <reflectiveEnable>false</reflectiveEnable>
                       <alert>%d</alert>
                       <alarm>%d</alarm>
                       <showTempStripEnable>true</showTempStripEnable>
                       <thermalOpticalTransmittance>1.000</thermalOpticalTransmittance>
                       <externalOpticsWindowCorrection>20.0</externalOpticsWindowCorrection>
                       <AlertOutputIOPortList>
                       <OutputIOPort>
                       <portID>1</portID>
                       <enabled>false</enabled>
                       </OutputIOPort>
                       </AlertOutputIOPortList>
                       <AlarmOutputIOPortList>
                       <OutputIOPort>
                       <portID>1</portID>
                       <enabled>false</enabled>
                       </OutputIOPort>
                       </AlarmOutputIOPortList>
                       <alertFilteringTime>0</alertFilteringTime>
                       <alarmFilteringTime>0</alarmFilteringTime>
                       <displayMaxTemperatureEnabled>true</displayMaxTemperatureEnabled>
                       <displayMinTemperatureEnabled>false</displayMinTemperatureEnabled>
                       <displayAverageTemperatureEnabled>false</displayAverageTemperatureEnabled>
                       <thermometryInfoDisplayposition>rules_around</thermometryInfoDisplayposition>
                       <calibrationCoefficientEnabled>false</calibrationCoefficientEnabled>
                       <displayTemperatureInOpticalChannelEnabled>false</displayTemperatureInOpticalChannelEnabled>
                       <calibrationFileVersion>V1.0.6.0 build201231</calibrationFileVersion>
                       <alarmInterval>%d</alarmInterval>
                       <rulesOverlayMode>alarm</rulesOverlayMode>
                       <alarmMode>alarm_alert</alarmMode>
                       <NormalRulesColor>
                       <R>0</R>
                       <G>255</G>
                       <B>0</B>
                       </NormalRulesColor>
                       </ThermometryBasicParam>)",
            alert,alarm,alarm_time);
    QByteArray array = QByteArray(buff);
    bool rtn = putWait(ip + "/ISAPI/Thermal/channels/2/thermometry/basicParam", array);

    qDebug()<< "SetAlarmPara rtn =" << rtn << endl;
    return rtn;
}

bool MyNetManager::GetPicture()
{
    qDebug() << QString("GetPicture")<< endl;
    QNetworkRequest request;
    QUrl qurl = QUrl(ip + "/ISAPI/Streaming/channels/2/picture");
    qurl.setUserName("admin");
    qurl.setPassword("YN123456789");
    request.setRawHeader("Connection","Keep-Alive");
    request.setUrl(qurl);
    QNetworkReply *reply = m_pManager->get(request);
    connect(reply,&QNetworkReply::finished,this,&MyNetManager::onCapPicRelyfinished);

    return true;
}


//23.8.14
bool MyNetManager::GetRealTimeTemperature()
{
    qDebug() << QString("GetRealTimeTemperature")<< endl;
    QNetworkRequest request;
    QUrl qurl = QUrl(ip + "/ISAPI/Thermal/channels/2/thermometry/1/rulesTemperatureInfo?format=json");
    qurl.setUserName("admin");
    qurl.setPassword("YN123456789");
    request.setRawHeader("Connection","Keep-Alive");
    request.setUrl(qurl);
    QNetworkReply *reply = m_pManager->get(request);
    connect(reply,&QNetworkReply::finished,this,&MyNetManager::onGetTemperatureRelyfinished);

    return true;
}

bool MyNetManager::KeepConnect()
{
    qDebug() << QString("KeepConnect");

    QNetworkRequest request;
    QUrl qurl = QUrl(ip + "/ISAPI/Event/notification/alertStream");
    qurl.setUserName("admin");
    qurl.setPassword("YN123456789");
    request.setRawHeader("Connection","Keep-Alive");
    request.setUrl(qurl);
    QNetworkReply* reply = m_pManager->get(request);
    connect(reply,SIGNAL(readyRead()),this,SLOT(onKeepRelyfinished()));
    connect(reply, static_cast<void (QNetworkReply::*)(QNetworkReply::NetworkError)>(&QNetworkReply::error),
         [=](QNetworkReply::NetworkError e){
        qDebug() << QString("onKeepConnectErr: %1\n").arg(e);
        emit sigKeepBrokeAlarm();
        KeepDisconnect();
    });



    keep = reply;
    qDebug() << "keep:" << keep;

    //启动倒计数15秒
    disconnect(keepTimer,0,0,0);
    connect(keepTimer, &QTimer::timeout, this, &MyNetManager::onKeepConnectTimeOut);
    keepTimer->start(connect_over_time_seconds);

    keepNetState = NET_CONNECTING;
    qDebug() << "KeepConnect start...\n";

    return true;
}

bool MyNetManager::KeepDisconnect()
{
    qDebug() << QString("KeepDisconnect\n");

    //m_pManager->clearConnectionCache();
    m_pManager->clearAccessCache();

    keepNetState = NET_DISCONNECT;
    keepTimer->stop();
    disconnect(keepTimer,0,0,0);

    if(keep == nullptr){
        return true;
    }
    //qDebug() << QString("disconnect\n");
    disconnect(keep,0,0,0);
    /*
    if(keep->isRunning()){
        qDebug()<< "keepRelayErrProcess keep->isRunning() true" << endl;
    }else{
        qDebug()<< "keepRelayErrProcess keep->isRunning() false" << endl;
    }
    qDebug() << QString("keep->close()\n");
    keep->close();
    qDebug() << QString("keep->abort()\n");
    keep->abort();
    */
    qDebug() << QString("keep->deleteLater()\n");
    keep->deleteLater();
    //keep = nullptr;


    return true;
}

bool MyNetManager::KeepReconnect()
{
    qDebug() << QString("KeepReconnect\n");
    KeepDisconnect();
    KeepConnect();
    return true;
}

NetState MyNetManager::KeepState()
{
    return keepNetState;
}

void MyNetManager::onKeepRelyfinished()
{

    QNetworkReply* reply = (QNetworkReply*)sender();
    if(reply->error() == QNetworkReply::NoError){

        qDebug() << QString("onKeepRelyfinished\n");
        keepRelayOkProcess(reply);

    }else{

        qDebug()<< "!!!!!! onKeepRelyfinished err:"<<reply->errorString()<<endl;
        keepRelayErrProcess(reply);
    }
}

void MyNetManager::onCapPicRelyfinished()
{
    qDebug("onCapPicRelyfinished\n");
    QDateTime dateTime;
    dateTime = QDateTime::currentDateTime();
    QString currentdatetime = dateTime.toString("yyyy_MM_dd hh_mm_ss");
    QNetworkReply* reply = (QNetworkReply*)sender();

    if(reply->error() == QNetworkReply::NoError){

        qDebug() << QString("onCapPicRelyfinished")<<endl;;
        capPicData = reply->readAll();
        emit sigCapPicture(capPicData);

    }else{
        qDebug()<< "onCapPicRelyfinished err: " << reply->errorString()<<endl;
    }

    reply->close();
    reply->deleteLater();
}


//23.8.14
//获取实时温度,解析数据方法未写
void MyNetManager::onGetTemperatureRelyfinished()
{
    qDebug() << "获取到实时温度!";

    QDateTime dateTime;
    dateTime = QDateTime::currentDateTime();
    QString currentdatetime = dateTime.toString("yyyy_MM_dd hh_mm_ss");
    QNetworkReply* reply = (QNetworkReply*)sender();


    if(reply->error() == QNetworkReply::NoError){

        qDebug() << QString("onGetTemperatureRelyfinished")<<endl;;
        responseData = reply->readAll();
        emit sigGetTemperature(responseData);

    }else{
        qDebug()<< "onGetTemperatureRelyfinished: " << reply->errorString()<<endl;
    }

    reply->close();
    reply->deleteLater();
}

bool MyNetManager::putWait(QString url, QByteArray &bytes)
{
    QNetworkRequest request;

    QUrl qurl = QUrl(url);
    qurl.setUserName("admin");
    qurl.setPassword("YN123456789");

    request.setUrl(qurl);
    request.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-www-form-urlencoded");
    QNetworkReply *reply = m_pManager->put(request, bytes);
    QEventLoop eventLoop;
    connect(reply, &QNetworkReply ::finished, &eventLoop, &QEventLoop::quit);
    eventLoop.exec();

    if(reply->error()!=QNetworkReply::NoError){
        //处理中的错误信息
        qDebug()<<"reply error:"<<reply->errorString()<<endl;;
        return false;

    }
    reply->deleteLater();

    return true;
}

void MyNetManager::keepRelayOkProcess(QNetworkReply *reply)
{
    qDebug() << "reply :" << reply << endl;
    if(keepNetState == NET_CONNECTING){
        keepNetState = NET_CONNECTED;

        qDebug() << "keepRelayOkProcess State == NET_CONNECTING\n" << endl;
        qDebug()<<"operation:"<<reply->operation();
        qDebug()<<"status code:"<<reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
        qDebug()<<"reply:"<<reply<< endl;

        connect_over_time_seconds = 15000;
        disconnect(keepTimer,0,0,0);
        connect(keepTimer, &QTimer::timeout, this, &MyNetManager::onKeepTimerOverProcess);
        keepTimer->start(11000);

        qDebug() << "KeepConnect ok\n";

    }else if(keepNetState == NET_CONNECTED){

        qDebug() << "keepRelayOkProcess State == NET_CONNECTED\n";
        qDebug()<<"reply:"<<reply<< endl;
        keepTimer->start(11000);
        QByteArray bytes = reply->readAll();

        //qDebug() << "recv:" << bytes << endl;
        QString qstr_byte = qPrintable(bytes);
        if (qstr_byte.contains("Temperature Measurement Alarm"))
        {
           emit sigTempAlarm(1);
           qDebug() << "Temperature Measurement Alarm1\n";
        }else{
           qDebug() << "recv heart beat!\n";
        }
    }
}

void MyNetManager::keepRelayErrProcess(QNetworkReply *reply)
{
    Q_UNUSED(reply);
    qDebug() << QString("keepRelayErrProcess\n");

    //当前处于连接状态,出错,需要告警
    if(keepNetState == NET_CONNECTED){
        emit sigKeepBrokeAlarm();
    }

    KeepDisconnect();
}

void MyNetManager::onKeepTimerOverProcess()
{
    qDebug() << "onKeepTimerOverProcess\n";
    //连接失败, 或者连接超时未接收到任何数据,告警
    emit sigKeepBrokeAlarm();
    KeepDisconnect();
}

static uint32_t time_add(uint32_t t)
{
    float val = t * 1.5;
    return (uint32_t)val;
}

void MyNetManager::onKeepConnectTimeOut()
{
    qDebug() << "onKeepConnectTimeOut\n";
    connect_over_time_seconds = time_add(connect_over_time_seconds) ;
    emit sigKeepBrokeAlarm();
    KeepDisconnect();
}

void MyNetManager::onKeepConnectFinished(QNetworkReply *reply)
{
    qDebug() << ">>onKeepConnectFinished:" << reply << endl;
}