#include "MqttSubscriber.h"
MqttSubscriber* MqttSubscriber::instance = nullptr;

MqttSubscriber* MqttSubscriber::getInstance(vides_data::MqttConfig& config, QObject* parent) {
    if (!instance) {
        instance = new MqttSubscriber(config, parent);
    }
    return instance;
}

MqttSubscriber::MqttSubscriber(vides_data::MqttConfig& config, QObject* parent)
    : QObject(parent), config(config) {

    QByteArray bAddress = config.address.toUtf8();
    char* cAddress=bAddress.data();


    QByteArray bClientId = config.clientId.toUtf8();
    char* cClientId=bClientId.data();


    MQTTAsync_create(&client,cAddress,cClientId, MQTTCLIENT_PERSISTENCE_NONE, nullptr);
    MQTTAsync_setCallbacks(client, this, [](void* context, char* cause) {
        static_cast<MqttSubscriber*>(context)->connectionLost(cause);
    }, [](void* context, char* topicName, int topicLen, MQTTAsync_message* m) {
        return static_cast<MqttSubscriber*>(context)->messageArrived(topicName, topicLen, m);
    }, nullptr);
}

MqttSubscriber::~MqttSubscriber() {
    MQTTAsync_destroy(&client);
    instance = nullptr;
}

void MqttSubscriber::start() {
    MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
    conn_opts.keepAliveInterval = 20;
    conn_opts.cleansession = 1;

    QByteArray bUsername = config.username.toUtf8();
    char* cUsername=bUsername.data();


    QByteArray bPassword = config.password.toUtf8();
    char* cPassword=bPassword.data();

    conn_opts.username = cUsername;
    conn_opts.password = cPassword;
    conn_opts.onSuccess = [](void* context, MQTTAsync_successData* response) {
        static_cast<MqttSubscriber*>(context)->onConnect(response);
    };
    conn_opts.onFailure = [](void* context, MQTTAsync_failureData* response) {
        static_cast<MqttSubscriber*>(context)->onConnectFailure(response);
    };
    conn_opts.context = this;

    int rc;
    if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS) {
        qInfo() << "启动连接失败，返回编码" << rc;
    }
}

void MqttSubscriber::onConnect(MQTTAsync_successData* response) {
    MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer;
    opts.onSuccess = [](void* context, MQTTAsync_successData* response) {
        static_cast<MqttSubscriber*>(context)->onSubscribe(response);
    };
    opts.onFailure = [](void* context, MQTTAsync_failureData* response) {
        static_cast<MqttSubscriber*>(context)->onSubscribeFailure(response);
    };
    opts.context = this;

    QByteArray bTopic = config.topic.toUtf8();
    char* cTopic=bTopic.data();
    int rc;
    if ((rc = MQTTAsync_subscribe(client, cTopic, config.qos, &opts)) != MQTTASYNC_SUCCESS) {
        qInfo() << "启动订阅失败，返回编码" << rc<<response->token;
    }
}

void MqttSubscriber::onConnectFailure(MQTTAsync_failureData* response) {
    qInfo() << "连接失败, rc" << (response ? response->code : -1);
}

void MqttSubscriber::onSubscribe(MQTTAsync_successData* response) {
    qInfo() << "订阅成功"<<response->token;
}

void MqttSubscriber::onSubscribeFailure(MQTTAsync_failureData* response) {
    qInfo() << "订阅失败, rc" << (response ? response->code : -1);
}

void MqttSubscriber::connectionLost(char* cause) {
    qInfo() << "连接丢失";
    if (cause) {
        qInfo() << "Cause:" << cause;
    }
}

int MqttSubscriber::messageArrived(char* topicName, int topicLen, MQTTAsync_message* m) {
    QString topic(topicName);
    QString payload = QString::fromUtf8(reinterpret_cast<const char*>(m->payload), m->payloadlen);

    qInfo() << "Message arrived";
    qInfo() << "Topic:" << topic;
    qInfo() << "Payload:" << payload;
    qInfo()<<"topicLen"<<topicLen;
    MQTTAsync_freeMessage(&m);
    MQTTAsync_free(topicName);
    return 1;
}

void MqttSubscriber::sendSubscriptionConfirmation(const std::string& messageId) {
    std::string confirmationTopic = "confirmation/subscription";
    std::string confirmationMessage = "Subscription confirmed with message ID: " + messageId;

    MQTTAsync_message pubmsg = MQTTAsync_message_initializer;
    pubmsg.payload = const_cast<char*>(confirmationMessage.c_str());
    pubmsg.payloadlen = confirmationMessage.length();
    pubmsg.qos = config.qos;
    pubmsg.retained = 0;

    MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer;
    opts.onSuccess = [](void* context, MQTTAsync_successData* response) {
        static_cast<MqttSubscriber*>(context)->onPublishSuccess(response);
    };
    opts.onFailure = [](void* context, MQTTAsync_failureData* response) {
        static_cast<MqttSubscriber*>(context)->onPublishFailure(response);
    };
    opts.context = this;

    int rc;
    if ((rc = MQTTAsync_sendMessage(client, confirmationTopic.c_str(), &pubmsg, &opts)) != MQTTASYNC_SUCCESS) {
        qInfo() << "发送消息失败，返回编码" << rc;
    }
}

void MqttSubscriber::onPublishSuccess(MQTTAsync_successData* response) {
    qInfo() << "消息已成功发布"<<response->token;
}

void MqttSubscriber::onPublishFailure(MQTTAsync_failureData* response) {
    qInfo() << "消息发布失败, rc" << (response ? response->code : -1);
}
