package cn.reghao.autodop.dmaster.mqttsub;

import cn.reghao.autodop.common.msg.Message;
import cn.reghao.autodop.common.msg.MsgType;
import cn.reghao.autodop.common.msg.pub.PubMsg;
import cn.reghao.autodop.common.msg.pub.clazz.PubClazz;
import cn.reghao.autodop.common.msg.rpc.RpcPayload;
import cn.reghao.autodop.common.msg.rpc.RpcMsg;
import cn.reghao.autodop.common.msg.rpc.RpcResult;
import cn.reghao.autodop.common.msg.rpc.clazz.RpcClazz;
import cn.reghao.autodop.dmaster.mqttsub.rpcresult.AppRpcClazzResult;
import cn.reghao.autodop.dmaster.mqttsub.impl.NodePubClazzHandler;
import cn.reghao.autodop.dmaster.mqttsub.rpcresult.DockerRpcClazzResult;
import cn.reghao.autodop.dmaster.mqttsub.rpcresult.MachineRpcClazzResult;
import cn.reghao.jdkutil.serializer.JsonConverter;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.springframework.stereotype.Component;

/**
 * 处理 sub.dmaster topic 中的消息
 *
 * @author reghao
 * @date 2021-05-24 09:24:03
 */
@Slf4j
@Component
public class MessageListener implements MqttCallback {
    private final NodePubClazzHandler nodeClazzPubResult;
    private final MachineRpcClazzResult machineRpcClazzResult;
    private final AppRpcClazzResult appRpcClazzResult;
    private final DockerRpcClazzResult dockerRpcClazzResult;

    public MessageListener(NodePubClazzHandler nodeClazzPubResult, MachineRpcClazzResult machineRpcClazzResult,
                           AppRpcClazzResult appRpcClazzResult, DockerRpcClazzResult dockerRpcClazzResult) {
        this.nodeClazzPubResult = nodeClazzPubResult;
        this.machineRpcClazzResult = machineRpcClazzResult;
        this.appRpcClazzResult = appRpcClazzResult;
        this.dockerRpcClazzResult = dockerRpcClazzResult;
    }

    @Override
    public void messageArrived(String topic, MqttMessage message) {
        try {
            if (message.isDuplicate()) {
                log.info("重新发送的消息");
            }

            String msg = message.toString();
            Message message1 = JsonConverter.jsonToObject(msg, Message.class);
            String msgType = message1.getMsgType();
            switch (MsgType.valueOf(msgType)) {
                case pub:
                    processPubMsg(message1.getPubMsg());
                    break;
                case rpc:
                    processRpcResult(message1.getRpcMsg());
                    break;
                default:
            }
        } catch (Exception e) {
            log.error("MQTT message exception -> {}", e.getMessage());
        }
    }

    private void processPubMsg(PubMsg pubMsg) {
        String clazz = pubMsg.getClazz();
        String method = pubMsg.getMethod();
        String jsonPayload = pubMsg.getJsonPayload();
        switch (PubClazz.valueOf(clazz)) {
            case NodePubClazz:
                nodeClazzPubResult.process(method, jsonPayload);
                break;
            default:
                ;
        }
    }

    private void processRpcResult(RpcMsg rpcMsg) {
        String msgId = rpcMsg.getMsgId();
        RpcPayload rpcPayload = rpcMsg.getRpcPayload();
        String clazz = rpcPayload.getClazz();
        String method = rpcPayload.getMethod();
        RpcResult rpcResult = rpcMsg.getRpcResult();
        switch (RpcClazz.valueOf(clazz)) {
            case AppRpcClazz:
                appRpcClazzResult.process(msgId, method, rpcResult);
                break;
            case MachineRpcClazz:
                machineRpcClazzResult.process(msgId, method, rpcResult);
                break;
            case DockerRpcClazz:
                dockerRpcClazzResult.process(msgId, method, rpcResult);
                break;
            default:
                ;
        }
    }

    @Override
    public void deliveryComplete(IMqttDeliveryToken token) {
    }

    @Override
    public void connectionLost(Throwable cause) {
        log.error("MQTT connection lost -> {}", cause.getMessage());
    }
}
