package com.yfd.platform.component.iec104.client;

import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yfd.platform.component.iec104.enums.QualifiersEnum;
import com.yfd.platform.component.iec104.enums.TypeIdentifierEnum;
import com.yfd.platform.component.iec104.message.MessageDetail;
import com.yfd.platform.component.iec104.message.MessageInfo;
import com.yfd.platform.component.iec104.server.master.BootNettyClientChannel;
import com.yfd.platform.component.iec104.server.master.BootNettyClientChannelCache;
import com.yfd.platform.modules.auxcontrol.domain.DeviceSignal;
import com.yfd.platform.modules.auxcontrol.domain.GatewayDevice;
import com.yfd.platform.modules.auxcontrol.domain.MeterDevice;
import com.yfd.platform.modules.auxcontrol.service.IDeviceSignalService;
import com.yfd.platform.modules.auxcontrol.service.IGatewayDeviceService;
import com.yfd.platform.modules.auxcontrol.service.IMeterDeviceService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
public class IIEC104Service {

    @Resource
    private IMeterDeviceService meterDeviceService;
    @Resource
    private IGatewayDeviceService gatewayDeviceService;
    @Resource
    private IDeviceSignalService deviceSignalService;

    public boolean sendCommand(String systemcode, String signalid, String type, String value) {

        DeviceSignal deviceSignal = deviceSignalService.getById(signalid);
        //辅控系统下属网关机状态监控
        if (StrUtil.isNotEmpty(systemcode) && "10".equals(systemcode)) {
            if (ObjUtil.isNotEmpty(deviceSignal)) {
                LambdaQueryWrapper<GatewayDevice> queryWrapper = new LambdaQueryWrapper<>();
                //类型
                queryWrapper.eq(GatewayDevice::getDeviceType, "30");
                //通讯网关机的iec地址
                queryWrapper.eq(GatewayDevice::getIecAddr, deviceSignal.getYxAddr());
                //查找网关机
                GatewayDevice gatewayDevice = gatewayDeviceService.getOne(queryWrapper);
                //连接到主机
                if ("1".equals(value)) {
                    //连接到子系统的通讯网关
                    gatewayDeviceService.connectToSlave(gatewayDevice.getIpAddr());
                } else {
                    //断开与子系统通讯网关的连接
                    gatewayDeviceService.disconnectToSlave(gatewayDevice.getIpAddr());
                }
            }
        } else {
            if (ObjUtil.isNotEmpty(deviceSignal)) {
                //查找设备
                MeterDevice meterDevice = meterDeviceService.getById(deviceSignal.getMeterDeviceId());
                LambdaQueryWrapper<GatewayDevice> queryWrapper = new LambdaQueryWrapper<>();
                //通讯网关机的IP地址
                queryWrapper.eq(GatewayDevice::getIpAddr, meterDevice.getNetdeviceIp());
                //查找网关机
                GatewayDevice gatewayDevice = gatewayDeviceService.getOne(queryWrapper);
                if (ObjUtil.isEmpty(gatewayDevice)) {
                    return false;
                }
                int iecaddr = gatewayDevice.getIecAddr();
                String address = "";
                if ("yk".equals(type)) {
                    address = deviceSignal.getYkAddr();
                } else if ("yt".equals(type)) {
                    address = deviceSignal.getYtAddr();
                }
                MessageDetail comand = getYk_YtCommand(iecaddr, deviceSignal.getYkytType(), address, value);
                //以上都是自加的
                if (BootNettyClientChannelCache.channelMapCache.size() <= 0) {
                    return false;
                }
                for (Map.Entry<String, BootNettyClientChannel> entry :
                        BootNettyClientChannelCache.channelMapCache.entrySet()) {
                    BootNettyClientChannel bootNettyChannel = entry.getValue();
                    if (bootNettyChannel == null || !bootNettyChannel.getChannel().isOpen()) {
                        //对应的终端
                        continue;
                    }
                    if (bootNettyChannel.getCode().equals(meterDevice.getNetdeviceIp())) {
                        bootNettyChannel.getChannel().writeAndFlush(comand);
                    }
                }
            }
        }
        return false;
    }

    private MessageDetail getYk_YtCommand(int terminalAddress, String type, String address, String value) {
        // 接收序号
        short accept = 0;
        // 发送序号
        short send = 0;
        //控制欲
        byte[] control = com.ydl.iec.util.Iec104Util.getIcontrol(accept, send);
        //类型标识 2D
        TypeIdentifierEnum typeIdentifierEnum = null;
        // 消息地址 总召唤地址为0
        //偏差  6000H
        int messageAddress = Integer.parseInt(address) + 24576;
        List<MessageInfo> messages = new ArrayList<>();
        MessageInfo message = new MessageInfo();
        //单点
        if ("01".equals(type)) {
            typeIdentifierEnum = TypeIdentifierEnum.onePointTelecontrol;
            if ("0".equals(value)) {
                message.setMessageInfos(new byte[]{0x00});
            }
            if ("1".equals(value)) {
                message.setMessageInfos(new byte[]{0x01});
            }
        } else if ("02".equals(type)) {
            //双点
            typeIdentifierEnum = TypeIdentifierEnum.twoPointTelecontrol;
            if ("0".equals(value)) {
                message.setMessageInfos(new byte[]{0x01});
            }
            if ("1".equals(value)) {
                message.setMessageInfos(new byte[]{0x02});
            }
        } else if ("03".equals(type)) {
            //遥调 -归一化值
            typeIdentifierEnum = TypeIdentifierEnum.normalizedTeleadjustment;
            short value1 = Short.parseShort(value);
            byte[] byteArray = new byte[2];
            // 低位字节
            byteArray[0] = (byte) (value1 & 0xFF);
            // 高位字节
            byteArray[1] = (byte) ((value1 >> 8) & 0xFF);
            message.setMessageInfos(byteArray);
        } else if ("04".equals(type)) {
            //遥调 -标度化值
            typeIdentifierEnum = TypeIdentifierEnum.scaledTeleadjustment;
            short value1 = Short.parseShort(value);
            byte[] byteArray = new byte[2];
            // 低位字节
            byteArray[0] = (byte) (value1 & 0xFF);
            // 高位字节
            byteArray[1] = (byte) ((value1 >> 8) & 0xFF);
            message.setMessageInfos(byteArray);
        } else if ("05".equals(type)) {
            //遥调 -浮点数值
            typeIdentifierEnum = TypeIdentifierEnum.shortFloatingPointTeleadjustment;
            byte[] byteArray = new byte[4];
            float value1 = Float.parseFloat(value);
            int intBits = Float.floatToIntBits(value1);
            // 第一个字节（最低位）
            byteArray[0] = (byte) (intBits & 0xFF);
            // 第二个字节
            byteArray[1] = (byte) ((intBits >> 8) & 0xFF);
            // 第三个字节
            byteArray[2] = (byte) ((intBits >> 16) & 0xFF);
            // 第四个字节（最高位）
            byteArray[3] = (byte) ((intBits >> 24) & 0xFF);
            message.setMessageInfos(byteArray);
        }
        message.setMessageAddress(messageAddress);
        messages.add(message);
        short terminalAddress1 = (short) terminalAddress;
        //SQ=0 length =1
        //        int sq = 0;
        //可变结构限定词 01
        //        boolean isContinuous = sq == 0 ? false : true;
        boolean isContinuous = false;
        // 传输原因
        short transferReason = 6;
        //公共地址
        // true：1 ; false ： 0
        boolean isTest = false;
        // true:0 false;1  isPn 肯定确认 和否定确认
        boolean isPN = true;
        MessageDetail ruleDetail104 = new MessageDetail(control, typeIdentifierEnum, isContinuous, isTest, isPN,
                transferReason,
                terminalAddress1, messageAddress, messages, null, null);
        if ("03".equals(type) || "04".equals(type) || "05".equals(type)) {
            QualifiersEnum qualifiers = QualifiersEnum.qualityQualifiers;
            ruleDetail104 = new MessageDetail(control, typeIdentifierEnum, isContinuous, isTest, isPN, transferReason,
                    terminalAddress1, messageAddress, messages, null, qualifiers);
        }
        return ruleDetail104;
    }
}
