/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of maveod.
* This project including source code and documentation is protected by
* copyright law, and remains the property of nymea GmbH. All rights, including
* reproduction, publication, editing and translation, are reserved. The use of
* this project is subject to the terms of a license agreement to be concluded
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
* under https://nymea.io/license
*
* For any further details and any questions please contact us under
* contact@nymea.io or see our FAQ/Licensing Information on
* https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#include "debugserver.h"
#include "loggingcategories.h"

#include <QJsonDocument>
#include <QJsonParseError>

DebugServer::DebugServer(QObject *parent) :
    QObject(parent)
{
    m_server = new QLocalServer(this);
    m_server->setSocketOptions(QLocalServer::UserAccessOption);

    if (!m_server->listen(m_serverName)) {
        qCWarning(dcDebugServer()) << "Could not listen on" << m_serverName << m_server->errorString();
        m_server->deleteLater();
        m_server = nullptr;
        return;
    }

    connect(m_server, &QLocalServer::newConnection, this, &DebugServer::onNewConnection);
    qCDebug(dcDebugServer()) << "Listening on" << m_server->serverName() << m_server->socketOptions();
}

void DebugServer::onNewConnection()
{
    QLocalSocket *client = m_server->nextPendingConnection();
    qCDebug(dcDebugServer()) << "New client connected on" << m_server->serverName() << client;

    connect(client, &QLocalSocket::readyRead, this, [this, client]() {
        QByteArray data = client->readAll();
        qCDebug(dcDebugServer()) << "Client data received:" << data;

        // Parse payload
        QJsonParseError error;
        QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
        if (error.error != QJsonParseError::NoError) {
            qCWarning(dcDebugServer()) << "Got invalid JSON data from client" << client << error.offset << error.errorString();
            sendResponse(client, false, QString("Invalid JSON data. Error: %1").arg(error.errorString()));
            return;
        }

        // Validate API
        QVariantMap requestMap = jsonDoc.toVariant().toMap();
        if (!requestMap.contains("button") || !requestMap.contains("action")) {
            qCWarning(dcDebugServer()) << "Invalid debug server API. Closing the connection.";
            sendResponse(client, false, "Invalid API format.");
            return;
        }

        // Validate button
        if (requestMap.value("button").toString() != "user" && requestMap.value("button").toString() != "reset") {
            qCWarning(dcDebugServer()) << "Invalid button value. Closing the connection.";
            sendResponse(client, false, "Invalid button value. Please use \'user\' or \'reset\' as button value.");
            return;
        }

        // Validate action
        if (requestMap.value("action").toString() != "click" && requestMap.value("action").toString() != "longpress") {
            qCWarning(dcDebugServer()) << "Invalid action value. Closing the connection.";
            sendResponse(client, false, "Invalid action value. Please use \'click\' or \'longpress\' as action value.");
            return;
        }

        if (requestMap.value("button").toString() == "user") {
            if (requestMap.value("action").toString() == "click") {
                qCDebug(dcDebugServer()) << "Click user button";
                emit userButtonClicked();
                sendResponse(client, true, "User button clicked.");
                return;
            }

            if (requestMap.value("action").toString() == "longpress") {
                qCDebug(dcDebugServer()) << "Long press user button";
                emit userButtonLongPressed();
                sendResponse(client, true, "User button long pressed.");
                return;
            }
        }

        if (requestMap.value("button").toString() == "reset") {
            if (requestMap.value("action").toString() == "click") {
                qCDebug(dcDebugServer()) << "Click reset button";
                emit resetButtonClicked();
                sendResponse(client, true, "Reset button clicked.");
                return;
            }

            if (requestMap.value("action").toString() == "longpress") {
                qCDebug(dcDebugServer()) << "Long press reset button";
                emit resetButtonLongPressed();
                sendResponse(client, true, "Reset button long pressed.");
                return;
            }
        }
    });

    connect(client, &QLocalSocket::disconnected, this, [client]() {
        qCDebug(dcDebugServer()) << "Client disconnected" << client;
        client->deleteLater();
    });

}

void DebugServer::sendResponse(QLocalSocket *client, bool success, const QString &message)
{
    QVariantMap response;
    response.insert("success", success);
    response.insert("message", message);
    QByteArray responseData = QJsonDocument::fromVariant(response).toJson();
    client->write(responseData);
    client->flush();
    client->close();
}


