package com.zt.plat.module.qms.iot.tcpserver.caaclient;

import com.zt.plat.module.qms.iot.tcpserver.IotUtils;
import com.zt.plat.module.qms.iot.tcpserver.cluster.TioServerMessageConfig;
import com.zt.plat.module.qms.iot.tcpserver.cluster.TioServerMessagePublisher;
import com.zt.plat.module.qms.iot.tcpserver.cluster.TioServerMessageVo;
import com.zt.plat.module.qms.iot.tcpserver.core.*;
import com.zt.plat.module.qms.iot.tcpserver.core.ChannelContextConstant;
import com.zt.plat.module.qms.iot.tcpserver.core.ClientType;
import com.zt.plat.module.qms.iot.tcpserver.core.Command;
import com.zt.plat.module.qms.iot.tcpserver.core.IotDeviceSessionForRedisContext;
import com.zt.plat.module.qms.iot.tcpserver.device.RedisSessionComponent;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zt.plat.module.qms.iot.tcpserver.IotPacket;
import com.zt.plat.module.qms.iot.tcpserver.caaclient.bean.ControlDevice;
import com.zt.plat.module.qms.iot.tcpserver.handler.IotDataHander;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import tech.zzjc.tio.cluster.TioClusterConfig;
import tech.zzjc.tio.cluster.TioClusterVo;
import tech.zzjc.tio.core.ChannelContext;
import tech.zzjc.tio.core.ChannelContextFilter;
import tech.zzjc.tio.core.Tio;
import tech.zzjc.tio.core.TioConfig;
import tech.zzjc.tio.core.stat.ChannelStat;

import java.nio.charset.Charset;
import java.util.Date;

import static com.zt.plat.module.qms.iot.tcpserver.core.GroupConstant.CAA_ALL_CLIENT;

/**
 * <b>IotCaaClientControlDeviceHander</b>
 * <p>更新历史：</p>
 * <pre> 版本         更新时间            更新者        更新内容
 * V1.0      2021-11-22          王兴荣         Add</pre>
 * <b>Copyright (C)  云南志者竟成科技有限公司</b> 
 * @author 王兴荣 &lt;xingrong_wang@will-way.cn&gt;
 * @version V1.0 
 * @since 2021-11-22
 */
@Slf4j
@Component
public class IotCaaClientControlDeviceHander implements IotDataHander {

    @Autowired public RedisSessionComponent redisSessionComponent;

    @Autowired
    private TioServerMessagePublisher tioServerMessagePublisher;

    @Override
    public Object hander(String msgId, String data, ChannelContext channelContext) throws Exception {
        ControlDevice controlDeviceOriginal = JSON.parseObject(data, ControlDevice.class);
        ControlDevice controlDevice = JSON.parseObject(data, ControlDevice.class);
        //获取客户端连接信息
        ChannelStat stat = channelContext.stat;
        String realClientIp = channelContext.get("realClientIp") == null ? channelContext.getClientNode().getIp() : channelContext.get("realClientIp").toString();
        String realClientPort = channelContext.get("realClientPort") == null ? channelContext.getClientNode().getPort() + "" : channelContext.get("realClientPort").toString();
        String deviceId = controlDevice.getDeviceId();
        String realClient = realClientIp + ":" + realClientPort;
        log.info("{}，, APP客户端控制设备 ：{}", realClient, controlDevice);
        JSONObject json = null;
        IotPacket iotPacket = new IotPacket();
        if (StringUtils.isBlank(deviceId)) {
            json = new JSONObject();
            json.put("msgId", msgId);
            json.put("cmd", Command.REPLY_CONTROL_DEVICE.getName());
            json.put("clientType", ClientType.CAA_CLIENT.getName());
            controlDevice.setSuccess(false);
            controlDevice.setMsg("设备解析为空！");
            json.put("data", controlDevice);
            iotPacket = new IotPacket();
            iotPacket.setBody((json.toJSONString() + "\r\n").getBytes(Charset.forName(IotPacket.CHARSET)));
            Tio.send(channelContext, iotPacket);
            return null;
        }
        IotDeviceSessionForRedisContext deviceContext = redisSessionComponent.getByDeviceId(deviceId);
        if (deviceContext == null) {
            //如果是订阅消息，不再广播
            if("1".equals(controlDevice.getFromSubscribe()))
                return null;
            json = new JSONObject();
            json.put("msgId", msgId);
            json.put("cmd", Command.REPLY_CONTROL_DEVICE.getName());
            json.put("clientType", ClientType.CAA_CLIENT.getName());
            controlDevice.setSuccess(false);
            controlDevice.setMsg("设备不在线！");
            json.put("data", controlDevice);
            iotPacket.setBody((json.toJSONString() + "\r\n").getBytes(Charset.forName(IotPacket.CHARSET)));
            Tio.send(channelContext, iotPacket);
            return null;
        }
        String deviceControlUserId = deviceContext.getUserId();
        String curUserId = controlDevice.getControlUserId();

        String deviceCode = IotUtils.transDeviceIdToCode(deviceId);
        ChannelContext deviceChannelContext = Tio.getByBsId(channelContext.getTioConfig(), deviceCode);
        //如果设备不在本服务实例，发送广播到其他服务处理
        if(deviceChannelContext == null){
            String channelId = deviceContext.getChannelId();
            TioServerMessageVo message = new TioServerMessageVo();
            message.setServerClusterMsgType(TioServerMessageConfig.MESSAGE_TYPE_CONTROL);
            message.setChannelId(channelId);
//            message.setChannelContext(channelContext);
            controlDeviceOriginal.setFromSubscribe("1");
            iotPacket.setBody((JSONObject.toJSONString(controlDeviceOriginal) + "\r\n").getBytes(Charset.forName(IotPacket.CHARSET)));
            message.setPacket(iotPacket);
            tioServerMessagePublisher.publish(message);
            return null;
        }

        TioConfig tioConfig = deviceChannelContext.getTioConfig();
        if (controlDevice.getIsControl()) {
            //控制
//            deviceContext.setControlChannelContext(channelContext);
            deviceContext.setControlRealName(controlDevice.getControlRealName());
            deviceContext.setUserId(curUserId);
            channelContext.set(ChannelContextConstant.CONTROL_DEVICE_ID, deviceCode);
            controlDevice.setMsg("设备被“" + controlDevice.getControlRealName() + "”远程控制！");
            redisSessionComponent.update(deviceContext);
        } else {
            //释放
            redisSessionComponent.clearControlByDeviceId(deviceId, channelContext);
            controlDevice.setMsg("“" + controlDevice.getControlRealName() + "”取消设备远程控制！");
        }

        //获取客户端连接信息
//        String deviceRealClientIp = deviceChannelContext.get("realClientIp") == null ? deviceChannelContext.getClientNode().getIp() : deviceChannelContext.get("realClientIp").toString();
//        String deviceRealClientPort = deviceChannelContext.get("realClientPort") == null ? deviceChannelContext.getClientNode().getPort() + "" : deviceChannelContext.get("realClientPort").toString();
//        String deviceRealClient = deviceRealClientIp + ":" + deviceRealClientPort;
//        log.info("{}， 设备：{}，旧控制：{}，新的控制：{}", realClient, deviceRealClient, oldDeviceChannelContext, realClient);

        json = new JSONObject();
        json.put("msgId", msgId);
        json.put("cmd", Command.REPLY_CONTROL_DEVICE.getName());
        json.put("clientType", ClientType.CAA_CLIENT.getName());
//        controlDevice.setSuccess(true);
//        json.put("data", controlDevice);
        json.put("data", JSON.parseObject(data, ControlDevice.class));
        iotPacket.setBody((json.toJSONString() + "\r\n").getBytes(Charset.forName(IotPacket.CHARSET)));
        //发送通知到其他服务实例（其他实例通知各自客户端）
        TioClusterConfig tioClusterConfig = tioConfig.getTioClusterConfig();
        TioClusterVo iotClusterVo = new TioClusterVo(iotPacket);
        iotClusterVo.setGroup(CAA_ALL_CLIENT);
        tioClusterConfig.publish(iotClusterVo);

        //发送消息到本服务实例连接的客户端
        Tio.sendToGroup(tioConfig, CAA_ALL_CLIENT, iotPacket, new ChannelContextFilter() {
            @Override
            public boolean filter(ChannelContext cc) {
                if (channelContext.getId().equals(cc.getId())) {
                    return false;
                }
                return true;
            }}
        );



        return null;
    }

}
