package com.yfd.platform.component.iec61850.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.beanit.iec61850bean.*;
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 com.yfd.platform.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.net.InetAddress;

@Service
public class IEC61850Service {

    private static final Logger log = LoggerFactory.getLogger(StringUtils.class);

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

    /**
     * 连接到设备并检索服务器模型
     *
     * @param gatewayDevice 设备信息
     */
    public boolean connect(GatewayDevice gatewayDevice) {
        ClientSap clientSap = new ClientSap();
        clientSap.setTSelRemote(new byte[]{0, 1});
        clientSap.setTSelLocal(new byte[]{0, 0});
        clientSap.setApTitleCalled(new int[]{1, 1, 999, 1});

        ClientAssociation clientAssociation = null;
        try {
            clientAssociation = clientSap.associate(InetAddress.getByName(gatewayDevice.getIpAddr()), 102, null,
                    clientListener);
            //保存到系统上下文中
            ClientConnetContext.put(gatewayDevice.getIpAddr(), clientAssociation);

            ServerModel serverModel = clientAssociation.retrieveModel();
            //"TEMPLATELD_Device0/LLN0.urcbAin1p01"
            String urcbs = gatewayDevice.getUrcb();
            if (StrUtil.isNotEmpty(urcbs)) {
                String[] urcbArray = urcbs.split(",");
                for (String s : urcbArray) {
                    Urcb urcb = serverModel.getUrcb(s);
                    clientAssociation.getRcbValues(urcb);
                    clientAssociation.reserveUrcb(urcb);
                    clientAssociation.enableReporting(urcb);
                }
            }
            //"TEMPLATELD_Device8/LLN0.brcbDin1p01"
            String brcbs = gatewayDevice.getBrcb();
            if (StrUtil.isNotEmpty(brcbs)) {
                String[] brcbArray = brcbs.split(",");
                for (String s : brcbArray) {
                    Brcb brcb = serverModel.getBrcb(s);
                    clientAssociation.getRcbValues(brcb);
                    clientAssociation.enableReporting(brcb);
                }
            }
            //sendCommand("", "a397bf1d4042ae948d248b1f1856937e", "yk", "true");
            //sendCommand("", "a397bf1d4042ae948d248b1f1856937e", "yt", "25.6");
        } catch (ServiceError | IOException e) {
            log.info("未能关联或检索设备的模型 {}: {}", gatewayDevice.getDeviceCode(), e.getMessage());
        }
        return true;
    }

    /**
     * 从服务器断开连接
     *
     * @param gatewayDevice 设备信息
     */
    public boolean disconnect(GatewayDevice gatewayDevice) {
        ClientAssociation association = (ClientAssociation) ClientConnetContext.get(gatewayDevice.getIpAddr());
        association.disconnect();
        return true;
    }

    /**
     * 给设备发送遥控、遥调命令
     * <p>
     * systemcode 系统编号
     * signalid 信号id
     * type  类型（yk、yt）
     * value
     */
    public boolean sendCommand(String systemcode, String signalid, String type, String value) throws IOException,
            ServiceError {

        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)) {
                    //连接到子系统的通讯网关
                    connect(gatewayDevice);
                } else {
                    //断开与子系统通讯网关的连接
                    disconnect(gatewayDevice);
                }
            }
        } else {
            if (ObjUtil.isNotEmpty(deviceSignal)) {
                //查找设备
                MeterDevice meterDevice = meterDeviceService.getById(deviceSignal.getMeterDeviceId());
                QueryWrapper<GatewayDevice> queryWrapper = new QueryWrapper<>();
                //通讯网关机的IP地址
                queryWrapper.eq("ip_addr", meterDevice.getNetdeviceIp());
                //查找网关机
                GatewayDevice gatewayDevice = gatewayDeviceService.getOne(queryWrapper);
                String convalue = value;
                if (ObjUtil.isNotEmpty(gatewayDevice)) {
                    String address = "";
                    if ("yk".equals(type)) {
                        convalue = "1".equals(value) ? "true" : "false";
                        address = deviceSignal.getYkAddr();
                    } else if ("yt".equals(type)) {
                        address = deviceSignal.getYtAddr();
                    }
                    //获取连接
                    ClientAssociation association =
                            (ClientAssociation) ClientConnetContext.get(meterDevice.getNetdeviceIp());
                    if (ObjUtil.isNotEmpty(association)) {
                        //检索模型
                        ServerModel serverModel = association.retrieveModel();
                        if ("true".equals(convalue) || "false".equals(convalue)) {
                            FcModelNode fcModelNode = (FcModelNode) serverModel.findModelNode(address, Fc.CO);
                            ModelNode oper = fcModelNode.getChild("Oper");
                            BdaBoolean ctlVal = (BdaBoolean) oper.getChild("ctlVal");
                            boolean b_value = Boolean.parseBoolean(convalue);
                            ctlVal.setValue(b_value);
                            association.operate(fcModelNode);
                        } else {
                            FcModelNode fcModelNode = (FcModelNode) serverModel.findModelNode(address, Fc.SP);
                            if (fcModelNode == null) {
                                throw new IllegalArgumentException("Model node not found for address: " + address);
                            }
                            // 获取 "SetVal" 子节点
                            ModelNode setValNode = fcModelNode.getChild("SetVal");
                            if (!(setValNode instanceof BdaFloat32)) {
                                throw new IllegalArgumentException("'SetVal' child node not found or not of type " +
                                        "BdaFloat32 for model node: " + address);
                            }
                            // 将 "SetVal" 子节点强制转换为 BdaFloat32 并设置值
                            BdaFloat32 setVal = (BdaFloat32) setValNode;
                            float temperature = Float.parseFloat(convalue);  // 目标温度值，例如 22.5 摄氏度
                            setVal.setFloat(temperature);
                            // 执行操作命令
                            association.setDataValues(fcModelNode);
                        }

                    }
                }
            }
        }
        return false;
    }

}

