#include <QCoreApplication>
#include <QTcpServer>
#include <QTcpSocket>
#include <QJsonDocument>
#include <QJsonObject>
#include <QByteArray>
#include <QImage>
#include <QDebug>

class HyperionMock : public QObject
{
    Q_OBJECT
public:
    HyperionMock(quint16 port, QObject *parent = nullptr) : QObject(parent)
    {
        _server = new QTcpServer(this);
        connect(_server, &QTcpServer::newConnection, this, &HyperionMock::handleConnection);
        if (!_server->listen(QHostAddress::Any, port)) {
            qCritical() << "Failed to start mock server:" << _server->errorString();
        } else {
            qDebug() << "Mock server listening on port" << port;
        }
    }

private slots:
    void handleConnection()
    {
        QTcpSocket *socket = _server->nextPendingConnection();
        QByteArray *buffer = new QByteArray();

        connect(socket, &QTcpSocket::readyRead, this, [this, socket, buffer]() {
            buffer->append(socket->readAll());

            int newlineIndex;
            while ((newlineIndex = buffer->indexOf('\n')) != -1) {
                // Extract the message including the newline
                QByteArray jsonData = buffer->left(newlineIndex + 1);
                buffer->remove(0, newlineIndex + 1);

                QJsonDocument doc = QJsonDocument::fromJson(jsonData.trimmed());
                if (doc.isObject()) {
                    QJsonObject obj = doc.object();
                    if (obj.contains("command") && obj["command"].toString() == "image") {
                        QJsonObject params = obj["params"].toObject();
                        int width = params["imagewidth"].toInt();
                        int height = params["imageheight"].toInt();
                        QByteArray imageData = QByteArray::fromBase64(params["imagedata"].toString().toUtf8());

                        if (width > 0 && height > 0 && !imageData.isEmpty()) {
                            QImage image(reinterpret_cast<const uchar*>(imageData.constData()), width, height, QImage::Format_RGB888);
                            if (!image.isNull()) {
                                QString filename = QString("received_frame_%1.png").arg(QUuid::createUuid().toString());
                                image.save(filename);
                                qDebug() << "Received and saved image:" << filename;

                                // Send success reply
                                QJsonObject reply;
                                reply["success"] = true;
                                reply["command"] = "image";
                                QByteArray replyData = QJsonDocument(reply).toJson(QJsonDocument::Compact);
                                replyData.append('\n');
                                socket->write(replyData);

                            } else {
                                qWarning() << "Failed to create QImage from raw data.";
                            }
                        } else {
                            qWarning() << "Invalid image dimensions or empty image data received.";
                        }
                    }
                } else {
                    qWarning() << "Failed to parse JSON object:" << jsonData.trimmed();
                }
            }
        });

        connect(socket, &QTcpSocket::disconnected, this, [socket, buffer]() {
            socket->deleteLater();
            delete buffer;
        });
    }


private:
    QTcpServer *_server;
};

int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);
    HyperionMock mock(19444);
    return app.exec();
}

#include "hyperion-mock.moc"
