#include "TokenRequest.h"

#include <QNetworkAccessManager>
#include <QUrlQuery>
#include <QNetworkRequest>

#include <QApplication>
#include <QFile>
#include <QJsonParseError>
#include <QJsonObject>

TokenRequest::TokenRequest(QObject* param) : QObject(param){
    GetConfig();

    m_networkAccessManager = new QNetworkAccessManager(this);
    Request();

    connect(&m_tokenTimer, &QTimer::timeout, [this]() {Request(); });
    m_tokenTimer.start(m_interval * 1000);
}

void TokenRequest::GetConfig() {
    const QString appName = qApp->applicationName();
    const QString path = qApp->applicationDirPath();
    const QString configPath = QString("%1/%2.data").arg(path, appName);
    
    QFile dataFile(configPath);
    if (!dataFile.open(QIODevice::ReadOnly)) {
        qDebug() << __FUNCTION__ << "couldn't open" << configPath;
        qApp->exit(1);
        return;
    }

    QByteArray allData = dataFile.readAll();
    dataFile.close();

    QJsonParseError jsonError;
    QJsonDocument jsonDoc(QJsonDocument::fromJson(allData, &jsonError));

    if (jsonError.error != QJsonParseError::NoError) {
        qDebug() << "json error!" << jsonError.errorString();
        return;
    }

    QJsonObject rootObj = jsonDoc.object();
    if (rootObj.contains("url")) {
        m_url = rootObj.value("url").toString();
    } else {
        qDebug() << __FUNCTION__ << "not contains url" << allData;
    }

    if (rootObj.contains("room")) {
        m_room = rootObj.value("room").toString();
    } else {
        qDebug() << __FUNCTION__ << "not contains room" << allData;
    }
   
    if (rootObj.contains("data")) {
        m_data = rootObj.value("data").toString();
    } else {
        qDebug() << __FUNCTION__ << "not contains data" << allData;
    }

    if (rootObj.contains("interval")) {
        m_interval = rootObj.value("interval").toInt();
    } else {
        qDebug() << __FUNCTION__ << "not contains data" << allData;
        m_interval = 60;
    }
}

void TokenRequest::SaveConfig() {
    QJsonObject rootObj;
    rootObj.insert("url", m_url);
    rootObj.insert("room", m_room);
    rootObj.insert("data", m_data);
    rootObj.insert("interval", m_interval);

    QJsonDocument jsonDoc;
    jsonDoc.setObject(rootObj);

    const QString appName = qApp->applicationName();
    const QString path = qApp->applicationDirPath();
    const QString configPath = QString("%1/%2.data").arg(path, appName);
    QFile dataFile(configPath);
    if (!dataFile.open(QIODevice::WriteOnly)) {
        qDebug() << __FUNCTION__ << "couldn't open" << configPath;

        return;
    }

    dataFile.write(jsonDoc.toJson());
    dataFile.close();
}

void TokenRequest::ParseData(const QString& data, bool net) {
    m_data = data;
    QStringList params = data.split("_");
    if (2 != params.count()) {
        QTimer::singleShot(m_interval, []() { qApp->exit(1); });
        return;
    }

    // Success代表正常、Failed代表失败要关闭。下划线NeedNet,表示写入配置项需要有网络,无网络访问则关闭。下划线NoNet,表示写入配置项不需要网络,无网络正常运行。
    if (net) {
        if ("Failed" == params[0]) {
            qDebug() << __FUNCTION__ << "exit Failed" << data;
            SaveConfig();
            qApp->exit(1);
            return;
        }
    } else {
        if ("NeedNet" == params[1]) {
            qDebug() << __FUNCTION__ << "exit NeedNet" << data;
            SaveConfig();
            qApp->exit(1);
            return;
        }
    }

    SaveConfig();
}

void TokenRequest::Request() {
    QUrlQuery query;
    query.addQueryItem("room", m_room);

    QUrl url(m_url);
    url.setQuery(query);
    QNetworkRequest request(url);
    auto reply = m_networkAccessManager->get(request);
    connect(reply, &QNetworkReply::finished, this, &TokenRequest::RequestFinished);
    connect(reply, &QNetworkReply::errorOccurred, this, &TokenRequest::ErrorOccurred);
}

void TokenRequest::RequestFinished() {
    QNetworkReply* reply = (QNetworkReply*)sender();
    
    QNetworkReply::NetworkError err = reply->error();
    if (err != QNetworkReply::NoError) {
        qDebug() << "Failed: " << reply->errorString();
    } else {
        // 获取返回内容
       const QString  data = reply->readAll();
       ParseData(data, true);
    }

    reply->deleteLater();
}

void TokenRequest::ErrorOccurred(QNetworkReply::NetworkError) {
    ParseData(m_data, false);
}