#include "ApismClientForUpdate.h"

#include <QRegularExpression>

ApismClientForUpdate::ApismClientForUpdate(QObject *parent)
    : ApismClient(parent) {

}

ApismClientForUpdate::~ApismClientForUpdate() {

}

void ApismClientForUpdate::sendCmdEvent(ISMAS::EventData eventData) {
    // QScopedPointer<ISMAS::EventData> eventData(new ISMAS::EventData());
 /*
    struct EventData : public QJsonObject {
        struct : public QJsonObject {
            QJsonValue reason;
            QJsonValue timestamp;
            QJsonValue eventID;
            QJsonValue event;
            QJsonValue eventState;
            struct : public QJsonObject {
                QJsonValue percent;
                QJsonValue resultCode;
                QJsonValue step;
                QJsonValue stepResult;
                QJsonValue Version;
            } parameter;
        } newsToIsmas;
    };

            "\"REASON\":\"SW_UP\","
            "\"TIMESTAMP\":\"%s\","
            "\"EVENT_ID\":\"0\","
            "\"EVENT\":\"%s\","
            "\"EVENTSTATE\":1,"
            "\"PARAMETER\": {"
                "\"PERCENT\" : %d,"
                "\"RESULTCODE\" : %d,"
                "\"STEP\" : \"%s\","
                "\"STEP_RESULT\" : \"%s\","
                "\"VERSION\" : \"%s\""
            "}"
        "}", ts.toStdStr

*/
    //eventData->newsToIsmas.reason = data.newsToIsmas;
    eventData.insert("REASON", eventData.newsToIsmas.reason);
    eventData.insert("TIMESTAMP", eventData.newsToIsmas.timestamp);
    eventData.insert("EVENT_ID", eventData.newsToIsmas.eventID);
    eventData.insert("EVENT", eventData.newsToIsmas.event);
    eventData.insert("EVENT_STATE", eventData.newsToIsmas.eventState);

    QJsonObject parameterJsonObject;
    parameterJsonObject.insert("PERCENT", eventData.newsToIsmas.parameter.percent);
    parameterJsonObject.insert("RESULTCODE", eventData.newsToIsmas.parameter.resultCode);
    parameterJsonObject.insert("STEP", eventData.newsToIsmas.parameter.step);
    parameterJsonObject.insert("STEP_RESULT", eventData.newsToIsmas.parameter.stepResult);
    parameterJsonObject.insert("VERSION", eventData.newsToIsmas.parameter.version);

    eventData.insert("PARAMETER", parameterJsonObject);

    qCritical() << __func__ << ":" << __LINE__ << eventData;

    QJsonDocument jsonDoc(eventData);
    QByteArray data = "#M=APISM#C=CMD_EVENT#J=";
    data += jsonDoc.toJson(QJsonDocument::Compact);

    qCritical() << __func__ << ":" << __LINE__ << data;

    tcpSendClient()->sendData(data);
}


void ApismClientForUpdate::onReceivedResponse(QByteArray response) {
    // get the root object
    QJsonParseError jsonParseError;
    QJsonDocument responseDoc = QJsonDocument::fromJson(response, &jsonParseError);

    if (jsonParseError.error != QJsonParseError::NoError) {
        qCritical() << "ApismClient::onReceivedResponse() response is no json data:";
        qCritical() << "     Error: " << jsonParseError.errorString();

        // workaround for REQ_SELF and offline
        if (this->getCurrentRequest() == ISMAS::REQUEST::SELF) {
            if (response.contains("Connecting...")) {
                qCritical() << "          -> Connecting...";
                return;
            }
            if (response.contains("ISMAS is offline")) {
                this->restartApism();
                qCritical() << "          -> Workaround: restart APISM";
                return;
            }
        }

        if (response.contains("ISMAS is offline")) {
            this->handleISMASOfflineResponseError();
            return;
        }
        else {
            this->handleISMASResponseError();
            return;
        }
    }

    QJsonObject rootObject = responseDoc.object();
    QStringList rootObjectKeys = rootObject.keys();

    // DEBUG
    qCritical() << "ApismClient::onReceivedResponse(): objects: " << rootObjectKeys;
    // results to:
    //  ApismClient::onReceivedResponse(): objects:  ("REQ_START#60044_Response", "Response")

    if(rootObjectKeys.indexOf(QRegularExpression("^CMD_GET_APISMSTATUS.*")) >= 0) {
        resetRetryCounter();
        //this->private_handleReqSelfResponse(rootObject["CMD_GET_APISMSTATUS_RESPONSE#0"].toObject());
    }
    else
    if(rootObjectKeys.indexOf(QRegularExpression("^REQ_ISMASPARAMETER.*")) >= 0) {
        resetRetryCounter();
        //this->private_handleParameterResponse(rootObject["Parameter"].toObject());
    }
    else
    if(rootObjectKeys.indexOf(QRegularExpression("^REQ_PING.*")) >= 0) {
        resetRetryCounter();
        //this->private_handleReqPingResponse(rootObject["PING"].toObject());
    }
    else
    if(rootObjectKeys.indexOf(QRegularExpression("^error")) >= 0) {
        // handle error objects
        //this->private_handleErrorResponse(rootObject["error"].toString());
    }
    else {
        qCritical() << "ApismClient::onReceivedResponse() for unknown Request: ";
        qCritical() << "                     currentRequestName: " << getCurrentRequest();
        qCritical() << "                      rootObject.keys(): " << rootObjectKeys;
        this->handleISMASResponseError();
        return;
    }

    this->setCurrentRequest(ISMAS::REQUEST::NO_REQUEST);
}

void ApismClientForUpdate::onSendClientResponseTimeout() {

}

void ApismClientForUpdate::onRequestResponseClientResponseTimeout() {
    qCritical() << "ApismClient::onRequestResponseClientResponseTimeout(): currentRequest is " << this->getCurrentRequest();

    switch (this->getCurrentRequest()) {
    case ISMAS::REQUEST::NO_REQUEST:
        break;
    case ISMAS::REQUEST::PING:
        //emit this->sendMininformPingResponse(nsApismInterface::RESULT_STATE::ERROR_TIMEOUT, QJsonObject());
        break;
    case ISMAS::REQUEST::SELF:
        //emit this->sendReqSelfResponse(nsApismInterface::RESULT_STATE::ERROR_TIMEOUT, QJsonObject());
        break;
    case ISMAS::REQUEST::PARAMETER:
        //emit this->sendReqParameterResponse(nsApismInterface::RESULT_STATE::ERROR_TIMEOUT, QJsonObject());
        break;
    }

    this->setCurrentRequest(ISMAS::REQUEST::NO_REQUEST);
}

void ApismClientForUpdate::onRequestResponseClientConnectTimeout() {

    qCritical() << "ApismClient::onRequestResponseClientConnectTimeout(): currentRequest is " << this->getCurrentRequest();

    nsApismInterface::RESULT_STATE resultState;

    resultState = nsApismInterface::RESULT_STATE::ERROR_BACKEND;

    switch (this->getCurrentRequest()) {
    case ISMAS::REQUEST::NO_REQUEST:
        qCritical() << "ApismClient::onRequestResponseClientConnectTimeout() for unknown Request: " << getCurrentRequest();
        break;
    case ISMAS::REQUEST::PING:
        //emit this->sendMininformPingResponse(resultState, QJsonObject());
        break;
    case ISMAS::REQUEST::SELF:
        //emit this->sendReqSelfResponse(resultState, QJsonObject());
        break;
    case ISMAS::REQUEST::PARAMETER:
        //emit this->sendReqParameterResponse(resultState, QJsonObject());
        break;
    }

    this->setCurrentRequest(ISMAS::REQUEST::NO_REQUEST);
}

void ApismClientForUpdate::onRequestResponseClientConnectionClosedByRemoteHost() {
    nsApismInterface::RESULT_STATE resultState = nsApismInterface::RESULT_STATE::ERROR_BACKEND;

    switch (this->getCurrentRequest()) {
    case ISMAS::REQUEST::NO_REQUEST:
        qCritical() << "ApismClient::onRequestResponseClientConnectionClosedByRemoteHost() for unknown Request: " << getCurrentRequest();
        break;
    case ISMAS::REQUEST::PING:
        //emit this->sendMininformPingResponse(resultState, QJsonObject());
        break;
    case ISMAS::REQUEST::SELF:
        emit this->sendReqSelfResponse(resultState, QJsonObject());
        break;
    case ISMAS::REQUEST::PARAMETER:
        emit this->sendReqParameterResponse(resultState, QJsonObject());
        break;
    }

    this->setCurrentRequest(ISMAS::REQUEST::NO_REQUEST);
}