package com.cisdi.data.caliper.gateway;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.cisdi.data.sdk.consts.ServiceName;
import com.cisdi.data.sdk.gateway.message.SocketMessage;
import com.cisdi.data.sdk.service.SendService;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @className: CaliperClientHandler
* @description: caliper客户端处理器
* @author: zhang.zhipeng
* @date: 2024/9/11 8:50
*/
@Slf4j
public class CaliperClientHandler extends SimpleChannelInboundHandler<ByteBuf> {
    private static final Charset Encode_Charset = StandardCharsets.UTF_8;
    private static final String HEARTBEAT_CODE = "HeartBea";

    private CaliperClient caliperClient;

    private final CaliperTaskStartVo startVo;

    public CaliperClientHandler(CaliperTaskStartVo startVo, CaliperClient caliperClient) {
        this.startVo = startVo;
        this.caliperClient = caliperClient;
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) {

        try {
            List<CaliperItemVo> decode = CaliperVoDecoder.Decode(msg);
            if(decode.size() == 1 && HEARTBEAT_CODE.equalsIgnoreCase(decode.get(0).getCode())) {
                log.info("Caliper {}，启用心跳：{} ， 心跳 vo:{}", caliperClient.getChannel(),
                        startVo.getCustomParam() != null && startVo.getCustomParam().getEnableHeartbeat(),
                        decode);
                caliperClient.setLastHeartbeatTime(System.currentTimeMillis());
                return;
            }

            decode.forEach((CaliperItemVo i) -> {
                i.setServerIp(startVo.getSocketParam().getPeerIp());
                i.setServerPort(startVo.getSocketParam().getPeerPort());
            });


            if (startVo.getGatewayBase() != null && Boolean.TRUE.equals(startVo.getGatewayBase().getInstanceVo().getLogOpen())) {
                log.info("Caliper {} vo:{} ", caliperClient.getChannel(), decode);
            }

            if (startVo.getGatewayBase() != null && startVo.getServiceProvider() != null) {
                Map<String, Object> data = new HashMap<>();
                SendService service = (SendService) startVo.getServiceProvider().getByName(ServiceName.Send);
                SocketMessage socketMessage = startVo.getGatewayBase().buildSocketMessage();
                socketMessage.setDeviceId(startVo.getDeviceId());
                socketMessage.setProviderCode(null);
                socketMessage.setMsgKey("666");
                data.put("data", decode);
                String jsonString = JSON.toJSONString(data, SerializerFeature.WriteMapNullValue);
                byte[] body = jsonString.getBytes(Encode_Charset);
                socketMessage.setData(body);
                log.info("socketMess{}", socketMessage);
                service.sendMessage(socketMessage);
            } else {
                log.info("Caliper收到消息{}", decode);
            }
        } catch (Exception e) {
            log.error(e.getLocalizedMessage(), e);
        }
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        log.info("{} channelActive active", ctx.channel());
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        log.info("{} channelInactive inactive", ctx.channel());

        try {
            caliperClient.setChannel(null);
            log.info("set channel to null raise reconnect");
        } finally {
            // 释放引用
            caliperClient = null;
        }

        super.channelInactive(ctx);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable t) throws Exception {
        log.error("exceptionCaught:", t);
        super.exceptionCaught(ctx, t);
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        log.error("userEventTriggered:{}", evt);
        super.userEventTriggered(ctx, evt);
    }
}
