#include <string>

#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkRequest>
#include <QtNetwork/QNetworkReply>
#include <QEventLoop>

#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonParseError>
#include <QJsonValue>
#include <QJsonObject>
#include <QJsonArray>

#include <QTimer>
#include <QSysInfo>
#include <QByteArray>
#include <QDataStream>

#include "device_information.h"
#include "global_variable.h"
#include "gsettings_monitor.h"
#include "information_collector.h"

QString devInfoPrint(const DeviceInformation &debugInfo)
{
    QString info = QString  (
              QString("\n")
            + QString("+++++++++++++++++++++++++++++++++\n")
            + QString("connectType  is: ") + QString::number(int(debugInfo.connectType))  + QString('\n')
            + QString("protocolType is: ") + QString::number(int(debugInfo.protocolType)) + QString('\n')
            + QString("name         is: ") + debugInfo.name         + QString('\n')
            + QString("vendor       is: ") + debugInfo.vendor       + QString("\n")
            + QString("model        is: ") + debugInfo.model        + QString("\n")
            + QString("serial       is: ") + debugInfo.serial       + QString("\n")
            + QString("uri          is: ") + debugInfo.uri          + QString("\n")
            + QString("packageName  is: ") + debugInfo.packagesName.join(",") + QString("\n")
            + QString("makeAndModel is: ") + debugInfo.makeAndModel + QString("\n")
            + QString("uuid         is: ") + debugInfo.uuid         + QString("\n")
    );
    if (debugInfo.connectType == ConnectType::InfoFrom_USB) {
        info += QString (
              QString("sysPath      is: ") + debugInfo.sysPath      + QString('\n')
            + QString("devicePath   is: ") + debugInfo.devicePath   + QString("\n")
            + QString("deviceType   is: ") + debugInfo.deviceType   + QString("\n")
            + QString("busNumber    is: ") + debugInfo.busNumber    + QString("\n")
            + QString("deviceNumber is: ") + debugInfo.deviceNumber + QString("\n")
            + QString("VID          is: ") + debugInfo.VID          + QString("\n")
            + QString("PID          is: ") + debugInfo.PID          + QString("\n")
        );
    }
    else {
    info += QString (
              QString("networkNode  is: ") + debugInfo.networkNode  + QString('\n')
            + QString("host         is: ") + debugInfo.host         + QString('\n')
            );
    }
    info +=  QString("+++++++++++++++++++++++++++++++++\n");
    return info;
}

QDebug operator << (QDebug debug, const DeviceInformation &debugInfo)
{
    debug.noquote();
    debug << devInfoPrint(debugInfo);
    return debug;
}

QStringList getPackagesNameFromHttp(DeviceInformation &device)
{
    QStringList res;


    QString arch = QSysInfo::currentCpuArchitecture();
    if (arch.contains("86")) {
        arch = "amd64";
    }
    else if (arch.contains("arm")) {
        arch = "arm64";
    }
    else if (arch.contains("mips")) {
        arch = "mips64el";
    } else if (arch.contains("sw")) {
        arch = "sw64";
    }
    // https://api.kylinos.cn/api/v1/getprinterdrive?systemVersion=V10&framework=arm64&pid=00a5&vid=04f9&product=Brother&model=HL-3190CDW
    // https://api.kylinos.cn/api/v1/getprinterdrive?systemVersion=V10Professional&arch=amd64&manufacter=cumtenn
    QString httpRequest = QString("https://%1/api/v1/getprinterdrive?systemVersion=%2&arch=%3%4%5%6%7")
                                .arg(GsettingsMonitor::getInstance()->apiServerAddressGet())
                                .arg(SYSTEM_VERSION)
                                .arg(arch)
                                .arg(device.PID.size() ? QString("&pid=" + device.PID) : "")
                                .arg(device.VID.size() ? QString("&vid=" + device.VID) : "")
                                .arg(device.vendor.size() ? QString("&manufacter=" + device.vendor) : "")
                                .arg(device.model.size() ? QString("&model=" + device.model) : "");
    // qDebug() << httpRequest;
    QNetworkAccessManager manager;
    QNetworkRequest netRequest;
    QNetworkReply *netReply;
    QEventLoop loop;
    qDebug () << "http link is :" << httpRequest;
    netRequest.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-www-form-urlencoded");
    netRequest.setUrl(QUrl(httpRequest));
    netReply = manager.get(netRequest);

    QTimer timer;
    QObject::connect(netReply, SIGNAL(finished()), &loop, SLOT(quit()));
    QObject::connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
    timer.start(10000);
    loop.exec();

    if (netReply->error() != QNetworkReply::NoError) {
        return res;
    }

    QByteArray strRateAll = netReply->readAll();
    qDebug() << "http result is"<<strRateAll;
    if (strRateAll == "") {
        qDebug() << "http request error: cannot get info form: " << httpRequest;
        return res;
    }
    QJsonParseError jsonParserError;
    QJsonDocument jsonDocument = QJsonDocument::fromJson(strRateAll, &jsonParserError );

    if ( jsonDocument.isNull() || jsonParserError.error != QJsonParseError::NoError ) {
        qDebug () << "json解析失败";
        return res;
    }
    else {
        qDebug() << "json解析成功!";
    }
    if (jsonDocument.isObject()) {
        QJsonObject jsonObject = jsonDocument.object();
        if ( jsonObject.contains("data")
            && jsonObject.value("data").isArray() ) {

            QJsonArray jsonArray = jsonObject.value("data").toArray();
            for ( int i = 0; i < jsonArray.size(); i++) {
                if (jsonArray.at(i).isString()) {
                    res.append(jsonArray.at(i).toString());
                }
            }
        }
    }
    device.packagesName = res;
    InformationCollector::getInstance().addMessage(QString("get %1 %2`s package list from %3:%4").arg(device.vendor)
                                                                                                 .arg(device.model)
                                                                                                 .arg(GsettingsMonitor::getInstance()->apiServerAddressGet())
                                                                                                 .arg(res.join(" ")));
    return res;
}
