package com.huimv.env.input.server;

import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.huimv.env.input.c.MyNativeClass;
import com.huimv.env.input.config.WeChatMessage;
import com.huimv.env.input.config.WeChatMessage2;
import com.huimv.env.input.entity.*;
import com.huimv.env.input.entity.vo.AlarmInfoVO;
import com.huimv.env.input.entity.vo.DataInfoVO;
import com.huimv.env.input.mapper.TerminalPortMapper;
import com.huimv.env.input.service.*;
import com.huimv.env.input.utils.ElePostUtils;
import com.huimv.env.input.ws.WebsocketWorkerUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;

import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import java.io.*;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import static com.huimv.env.input.timer.ElePostTimer.ALARM_URL;
import static com.huimv.env.input.timer.ElePostTimer.BASE_URL;

/**
 * @Project : huimv.shiwan
 * @Package : com.huimv.biosafety.uface.controller
 * @Description : TODO
 * @Version : 1.0
 * @Author : ZhuoNing
 * @Create : 2020-12-25
 **/
@ChannelHandler.Sharable
@Component
@Log4j2
public class EnvInputServerHandler extends ChannelInboundHandlerAdapter {
    private StringBuilder askTextSb = null;

    @Autowired
    private IEnvDataService envDataService;

    @Autowired
    private ITerminalPortService terminalPortService;

    @Autowired
    private IBaseFarmService baseFarmService;

    @Autowired
    private IBasePigpenService basePigpenService;

    @Autowired
    private IPortWarningInfoService portWarningInfoService;

    @Autowired
    private IPortChangeDataService portChangeDataService;

    @Autowired
    private ITerminalService terminalService;

    @Autowired
    private IHeartInfoService heartInfoService;
    @Autowired
    private IGatewayService gatewayService;



    @Autowired
    private ISysAccountMultilevelService sysAccountMultilevelService;
    //
    public void appendClientAsk(String text) {
        if (this.askTextSb == null) {
            askTextSb = new StringBuilder();
        }
        askTextSb.append(text);
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf data = (ByteBuf) msg;
        String clientAskText = data.toString(CharsetUtil.UTF_8);
        //保存实例内的客户端请求
        appendClientAsk(clientAskText);
        //临时写入耳标数据到文件
//        writeTxt(clientAskText,"all");
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        if (askTextSb.toString().indexOf("end") != -1) {
            // {处理客户端消息}
            handleClientAskCmd(askTextSb.toString(), ctx);
            //清空重置;
            askTextSb.delete(0, askTextSb.length());
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        if (cause.getMessage().indexOf("Connection reset") != -1) {
            log.info("相关采集器设备正在重启:" + cause.toString());
        }
//        cause.printStackTrace();
        ctx.close();
    }

    /**
     * @Method : handleClientAskCmd
     * @Description : 处理请求小心
     * @Params : [clientAskText, ctx]
     * @Return : void
     * @Author : ZhuoNing
     * @Date : 2022/3/28
     * @Time : 17:36
     */
    private void handleClientAskCmd(String clientAskText, ChannelHandlerContext ctx) throws  IOException {
        clientAskText = clientAskText.replaceAll("\r", "").replaceAll("\n", "");
        //{处理非正常命令}
//        int countPlus = regexUtil.countPlus(clientAskText);
//        if (countPlus < 4) {
//            System.out.println("当前数据为不完整数据，故丢弃.>>" + clientAskText);
//        } else {
        //--处理客户端请求数据
        //{拆分粘包数据}
        JSONArray askJa = parseAskCmdPackage(clientAskText);
        for (int a = 0; a < askJa.size(); a++) {
            String askText = askJa.getString(a);
            //{处理请求命令}
            askCmdActuator(askText, ctx);
        }
//        }
    }

    /**
     * @Method : askCmdActuator
     * @Description :
     * @Params : [askText, ctx]
     * @Return : void
     * @Author : ZhuoNing
     * @Date : 2022/3/23
     * @Time : 18:08
     */
    private void askCmdActuator(String askText, ChannelHandlerContext ctx) throws  IOException {
        System.out.println("======>接收设备请求:" + askText);
        String[] dataArray = askText.split("\\+");

        String cmdHeader = dataArray[0];
        if (!cmdHeader.trim().equalsIgnoreCase("hm")) {
            log.info("当前命令是非hm命令[" + askText + "]");
            return;
        }
        String version = dataArray[dataArray.length - 3];
        if ("v2.0".equals(version)) {
            askCmdActuatorV2(askText, ctx, dataArray);
        } else {
            askCmdActuatorV1(askText, ctx, dataArray);

        }
    }

    private void askCmdActuatorV2(String askText, ChannelHandlerContext ctx,  String[] dataArray) throws IOException {
        //芯片id/设备编码
        String cmd = dataArray[1];
        switch (cmd) {
            case "1":
                //心跳
                getHear(askText, dataArray, ctx,2);
                break;
            case "2":
                //上传数据
                getChuanGanData2(askText, dataArray, ctx);
                break;
            case "3":
                //充电前后功率
                savePower2(askText, dataArray, ctx);
                break;
            case "4":
                //充电中电流
                saveElectric2(askText, dataArray, ctx);
                break;
            case "5":
                //充电前电流
                saveBeforeElectric2(askText, dataArray, ctx);
                break;
            default:
                log.error(String.format("未知指令 --> %s", askText));
                answerCmd("hm+4+1+end", ctx);
        }
    }

    private  synchronized void saveBeforeElectric2(String askText, String[] dataArray, ChannelHandlerContext ctx) {

        String gateWayCode = dataArray[2];
        String  terminalCode = dataArray[3];
        String terminalPortCode = "1";
        String num = dataArray[4];
        String eleData = dataArray[5];
        Date now = new Date();

        try {
            PortChangeData portChangeData = portChangeDataService.getOne(new QueryWrapper<PortChangeData>().eq("terminal_port_code", gateWayCode + terminalCode + terminalPortCode).eq("num", num));
            if (ObjectUtils.isEmpty(portChangeData)) {
                portChangeData = new PortChangeData();
                portChangeData.setNum(Integer.parseInt(num));
                portChangeData.setCreateTime(now);
                portChangeData.setGatwayCode(gateWayCode);
                portChangeData.setTerminalCode(gateWayCode+terminalCode);
                portChangeData.setTerminalPortCode(gateWayCode+terminalCode+terminalPortCode);
                portChangeData.setBeforeElectricCurrent(eleData);
                portChangeDataService.save(portChangeData);
            }else {
                portChangeData.setBeforeElectricCurrent(eleData);
                portChangeDataService.updateById(portChangeData);
                if(changeDataIsAll(portChangeData)){
//                    int i  = getStatusEle(portChangeData);
                    int i  = getStatusEle2(portChangeData);
                    TerminalPort deviceCode = terminalPortService.getOne(new QueryWrapper<TerminalPort>().eq("device_code", portChangeData.getTerminalPortCode()));
                    System.out.println("---->"+i);
                    if (i == 1){
                        deviceCode.setChargingWarning(1);
                        String ans = "hm+5+1+end";
                        answerCmd(ans,ctx);
                        saveChargingWarning(portChangeData,deviceCode);
                        EnvData envData  = new EnvData();

                        envData.setActivePower(portChangeData.getActivePower());
                        pushAlarm(terminalCode +terminalPortCode,12,envData);
                    }else {
                        String ans = "hm+5+0+end";
                        answerCmd(ans,ctx);
                        deviceCode.setChargingWarning(0);
                    }
                    terminalPortService.updateById(deviceCode);
                }
            }
        }catch (Exception e){
            log.error(String.format("点位查询失败--> %s" ,askText));
            log.error(e);
        }
    }
    private int getStatusEle2(PortChangeData portChangeData) {
        // 前有功功率	前无功功率	前视在功率  +  前 128个电流值
        String[] lastEleData = portChangeData.getBeforeElectricCurrent().split(",");
        String[] lastGlData =new String[]{String.valueOf(portChangeData.getBeforeActivePower()),String.valueOf(portChangeData.getBeforeReactivePower()),String.valueOf(portChangeData.getBeforeApparentPower())};

        // 有功功率	无功功率	视在功率  +  128个电流值
        String[] curretEleData = portChangeData.getElectricCurrent().split(",");
        String[] curretGlData =new String[]{String.valueOf(portChangeData.getActivePower()),String.valueOf(portChangeData.getReactivePower()),String.valueOf(portChangeData.getApparentPower())};

        Object[] ints = Stream.concat( Arrays.stream(lastGlData),Arrays.stream(lastEleData)).toArray();
        Object[] ints1 = Stream.concat(Arrays.stream(curretGlData) ,Arrays.stream(curretEleData)).toArray();

//        return MyNativeClass.LibraryshowChar.LIBRARY_CHAR.current_detection(ints,ints1 );
        return add2(ints,ints1 );
//        return MyNativeClass.LibraryshowChar.LIBRARY_CHAR.current_detection( );
    }

    public  int add2(Object[] array1 ,  Object[] array2)   {

        // 步骤1: 将两个数组写入临时文件
        String tempInputFile = "temp_input.txt";
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(tempInputFile))) {
            String array1String = Arrays.stream(array1)
                    .map(Object::toString) // 使用 Object 的 toString 方法转换为 String
                    .collect(Collectors.joining(","));
            writer.write(array1String);
            writer.newLine(); // 换行

            // 写入第二个数组
            String array2String = Arrays.stream(array2)
                    .map(Object::toString) // 使用 Object 的 toString 方法转换为 String
                    .collect(Collectors.joining(","));
            writer.write(array2String);
            writer.newLine(); // 换行
        } catch (IOException e) {
            e.printStackTrace();
            return 0;
        }

        // 步骤2: 调用C程序
        String cProgramPath = "/root/svm_detection_c/predict"; // 替换为你的C程序的实际路径
        String tempOutputFile = "temp_output.txt"; // 假设C程序将结果写入此文件
        ProcessBuilder processBuilder = new ProcessBuilder(cProgramPath, tempInputFile, tempOutputFile);
        try {
            Process process = processBuilder.start();
            int exitCode = process.waitFor();
            if (exitCode != 0) {
                System.err.println("C program execution failed with exit code: " + exitCode);
                return 0;
            }
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
            return 0;
        }

        // 步骤3: 读取结果文件
        try (BufferedReader reader = new BufferedReader(new FileReader(tempOutputFile))) {
            String line;
            String str ="1";
            while ((line = reader.readLine()) != null) {
                System.out.println("line"+line); // 或者你可以将结果存储到某个变量或集合中
                str = line;
            }
            return Integer.parseInt(str);
        } catch (IOException e) {
            e.printStackTrace();
            return 0;
        }

        // 步骤4: 删除所有文件
//        Path inputFilePath = Paths.get(tempInputFile);
//        Path outputFilePath = Paths.get(tempOutputFile);
//        try {
//            Files.deleteIfExists(inputFilePath);
//            Files.deleteIfExists(outputFilePath);
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
    }



    private  synchronized void saveElectric2(String askText, String[] dataArray, ChannelHandlerContext ctx) {
        String ans = "hm+4+1+end";
        answerCmd(ans,ctx);
        String gateWayCode = dataArray[2];
        String  terminalCode = dataArray[3];
        String terminalPortCode = "1";
        String num = dataArray[4];
        String eleData = dataArray[5];
        Date now = new Date();

        try {
            PortChangeData portChangeData = portChangeDataService.getOne(new QueryWrapper<PortChangeData>().eq("terminal_port_code", gateWayCode + terminalCode + terminalPortCode).eq("num", num));
            if (ObjectUtils.isEmpty(portChangeData)) {
                portChangeData = new PortChangeData();
                portChangeData.setNum(Integer.parseInt(num));
                portChangeData.setCreateTime(now);

                portChangeData.setGatwayCode(gateWayCode);
                portChangeData.setTerminalCode(gateWayCode+terminalCode);
                portChangeData.setTerminalPortCode(gateWayCode+terminalCode+terminalPortCode);
                portChangeData.setElectricCurrent(eleData);

                portChangeDataService.save(portChangeData);
            }else {
                portChangeData.setElectricCurrent(eleData);
                portChangeDataService.updateById(portChangeData);

//                if(changeDataIsAll(portChangeData)){
//                    int i  = getStatusEle(portChangeData);
//                    TerminalPort deviceCode = terminalPortService.getOne(new QueryWrapper<TerminalPort>().eq("device_code", portChangeData.getTerminalPortCode()));
//                    if (i == 1){
//                        deviceCode.setChargingWarning(1);
//                        saveChargingWarning(portChangeData,deviceCode);
//                    }else {
//                        deviceCode.setChargingWarning(0);
//                    }
//                    terminalPortService.updateById(deviceCode);
//                }
            }
        }catch (Exception e){
            log.error(String.format("点位查询失败--> %s" ,askText));
            log.error(e);
        }
    }

    private synchronized void savePower2(String askText, String[] dataArray, ChannelHandlerContext ctx) {
        String ans = "hm+3+1+end";
        answerCmd(ans,ctx);
        String gateWayCode = dataArray[2];
        String  terminalCode = dataArray[3];
        String terminalPortCode = "1";
        String num = dataArray[4];
        int[] splitPower = Arrays.stream(dataArray[5].split(",")).mapToInt(Integer::parseInt).toArray();
        int[] splitBeforePower = Arrays.stream(dataArray[6].split(",")).mapToInt(Integer::parseInt).toArray();
        Date now = new Date();

        try {
            PortChangeData portChangeData = portChangeDataService.getOne(new QueryWrapper<PortChangeData>().eq("terminal_port_code", gateWayCode + terminalCode + terminalPortCode).eq("num", num));
            if (ObjectUtils.isEmpty(portChangeData)) {
                portChangeData = new PortChangeData(gateWayCode + terminalCode + terminalPortCode,gateWayCode + terminalCode ,gateWayCode,
                        splitPower[0],splitPower[1],splitPower[2],
                        splitBeforePower[0],splitBeforePower[1],splitBeforePower[2],
                        now,Integer.parseInt(num));
                portChangeDataService.save(portChangeData);
            }else {
                portChangeData.setActivePower( splitPower[0]);
                portChangeData.setReactivePower( splitPower[1]);
                portChangeData.setApparentPower( splitPower[2]);
                portChangeData.setBeforeActivePower(splitBeforePower[0]);
                portChangeData.setBeforeReactivePower(splitBeforePower[1]);
                portChangeData.setBeforeApparentPower(splitBeforePower[2]);
                portChangeDataService.updateById(portChangeData);

            }
        }catch (Exception e){
            log.error(String.format("点位查询失败--> %s" ,askText));
            log.error(e);
        }
    }

    private int getStatusEle(PortChangeData portChangeData) {
        // 前有功功率	前无功功率	前视在功率  +  前 128个电流值
        int[] lastEleData =  Arrays.stream(portChangeData.getBeforeElectricCurrent().split(",")).mapToInt(Integer::parseInt).toArray();
        int[] lastGlData = new int[]{portChangeData.getBeforeActivePower(),portChangeData.getBeforeReactivePower(),portChangeData.getBeforeApparentPower()};

        // 有功功率	无功功率	视在功率  +  128个电流值
        int[] curretEleData =Arrays.stream(portChangeData.getElectricCurrent().split(",")).mapToInt(Integer::parseInt).toArray();
        int[] curretGlData = new int[]{portChangeData.getActivePower(),portChangeData.getReactivePower(),portChangeData.getApparentPower()};
        int[] ints = IntStream.concat( Arrays.stream(lastGlData),Arrays.stream(lastEleData)).toArray();
        int[] ints1 = IntStream.concat(Arrays.stream(curretGlData) ,Arrays.stream(curretEleData)).toArray();

        System.out.println("last");
        for (int i : ints) {
            System.out.print(i+",");
        }
        System.out.println();
        System.out.println("curretData");
        for (int i : ints1) {
            System.out.print(i+",");
        }
        System.out.println();
        return MyNativeClass.LibraryshowChar.LIBRARY_CHAR.current_detection(ints,ints1 );
//        return MyNativeClass.LibraryshowChar.LIBRARY_CHAR.current_detection( );

    }

    private void saveChargingWarning(PortChangeData portChangeData ,TerminalPort deviceCode) {

        BasePigpen basePigpen = basePigpenService.getById(deviceCode.getLocationId());
        BasePigpen basePigpen1= basePigpenService.getById(basePigpen.getOther2().split(",")[1]);
        PortWarningInfo portWarningInfo = new PortWarningInfo();
        portWarningInfo.setGatwayCode(portChangeData.getGatwayCode());

        portWarningInfo.setTerminalCode(portChangeData.getTerminalCode());
        portWarningInfo.setTerminalPortCode(portChangeData.getTerminalPortCode());
        portWarningInfo.setLocationId(deviceCode.getLocationId());
        portWarningInfo.setFarmId(deviceCode.getFarmId());
        portWarningInfo.setWarningType(2);
        Date now = new Date();
        portWarningInfo.setCreateTime(now);
        portWarningInfo.setContent(String.format("%s 充电预警",basePigpen.getBuildName()));
        portWarningInfo.setWarningType(2);
        portWarningInfoService.save(portWarningInfo);

        List<SysAccountMultilevel> list = sysAccountMultilevelService.list(new QueryWrapper<SysAccountMultilevel>().eq("last_farm_id", deviceCode.getFarmId()).eq("subscribe", 1));
        for (SysAccountMultilevel sysAccountMultilevel : list) {
            WeChatMessage.sendMsg(now,"充电预警",basePigpen1.getBuildName(),basePigpen.getBuildName().substring(basePigpen1.getBuildName().length()),sysAccountMultilevel.getWechatId());
            WeChatMessage2.sendMsg(now,"充电预警",basePigpen1.getBuildName(),basePigpen.getBuildName().substring(basePigpen1.getBuildName().length()),sysAccountMultilevel.getWechatId());
            sysAccountMultilevel.setSubscribe(0);
            sysAccountMultilevelService.updateById(sysAccountMultilevel);
        }
        WebsocketWorkerUtil.sendWarningMessage(deviceCode.getFarmId(),String.format("%s 充电预警",basePigpen.getBuildName()));

    }

    private boolean changeDataIsAll(PortChangeData portChangeData) {
        return portChangeData.getActivePower() != null &&
                portChangeData.getBeforeActivePower() != null &&
                portChangeData.getReactivePower() != null &&
                portChangeData.getBeforeReactivePower() != null &&
                portChangeData.getApparentPower() != null &&
                portChangeData.getBeforeApparentPower() != null &&
                portChangeData.getElectricCurrent() != null &&
                portChangeData.getBeforeElectricCurrent() != null ;
    }

    private void getChuanGanData2(String askText, String[] dataArray, ChannelHandlerContext ctx) throws IOException {
        String ans = "hm+2+1+end";
        answerCmd(ans,ctx);
        //hm+2+867699060007086+1+2222+7+260+0+104,17,159+0,0+v2.0+24+end
        String gateWayCode = dataArray[2];
        String  terminalCode = dataArray[3];
        String terminalPortCode = "1";
        String voltage = getNum(dataArray[4]);
        String electriCurrent = getNum(dataArray[5]);
        String temp = getNum(dataArray[6]);
        String leakageValue = getNum(dataArray[7]);
        Date now = new Date();
        int[] splitPower = Arrays.stream(dataArray[8].split(",")).mapToInt(Integer::parseInt).toArray();
        int[] splitStatus =Arrays.stream(dataArray[9].split(",")).mapToInt(Integer::parseInt).toArray();
        EnvData envData = new EnvData(gateWayCode+terminalCode+terminalPortCode,gateWayCode+terminalCode,gateWayCode,
                voltage,electriCurrent,temp, leakageValue,
                splitPower[0],splitPower[1],splitPower[2],
                splitStatus[0],0,splitStatus[1],
                askText,now);
        envDataService.save(envData);
        //更新状态
//        try {
        TerminalPort deviceCode = terminalPortService.getOne(new QueryWrapper<TerminalPort>().eq("device_code", gateWayCode + terminalCode + terminalPortCode));
        if (ObjectUtils.isEmpty(deviceCode)){
            log.info(String.format("无端口设备--> %s" ,askText));
            return;
        }
        deviceCode.setVoltage(voltage);
        deviceCode.setElectricCurrent(electriCurrent);
        deviceCode.setTemp(temp);
        deviceCode.setLeakageValue(leakageValue);
        deviceCode.setActivePower( splitPower[0]);
        deviceCode.setReactivePower(splitPower[1]);
        deviceCode.setApparentPower(splitPower[2]);
        deviceCode.setHeightTempWarning( splitStatus[0]);
        deviceCode.setChargingWarning( 0);
        deviceCode.setLeakageWarning( splitStatus[1]);
        deviceCode.setUpdateTime(now);
        deviceCode.setStatus(1);
        terminalPortService.updateById(deviceCode);
        //添加报警
        saveWarning2(gateWayCode,terminalCode,terminalPortCode,deviceCode,splitStatus,now,envData);
    }
    private void saveWarning2(String gateWayCode,String terminaCode,String terminalPortCode ,TerminalPort terminalPort,int[] splitStatus,Date now,EnvData envData) throws IOException {
        if (splitStatus[0] == 0 && splitStatus[1] == 0 )
            return;
        Integer farmId = terminalPort.getFarmId();
        Integer locationId = terminalPort.getLocationId();

        BasePigpen basePigpen = basePigpenService.getById(locationId);
        BasePigpen basePigpen1= basePigpenService.getById(basePigpen.getOther2().split(",")[1]);
        if (ObjectUtils.isEmpty(basePigpen)){
            log.info(String.format("无栋舍数据--> %s" ,terminalPort.toString()));
            return;
        }

        PortWarningInfo portWarningInfo = new PortWarningInfo();
        portWarningInfo.setGatwayCode(gateWayCode);
        portWarningInfo.setTerminalCode(gateWayCode+terminaCode);
        portWarningInfo.setTerminalPortCode(gateWayCode+ terminaCode +terminalPortCode);
        portWarningInfo.setLocationId(locationId);
        portWarningInfo.setFarmId(farmId);
        portWarningInfo.setWarningType(farmId);
        portWarningInfo.setCreateTime(now);
        if (splitStatus[0] == 1){
            portWarningInfo.setContent(String.format("%s 高温预警",basePigpen.getBuildName()));
            portWarningInfo.setWarningType(1);
            portWarningInfoService.save(portWarningInfo);
            List<SysAccountMultilevel> list = sysAccountMultilevelService.list(new QueryWrapper<SysAccountMultilevel>().eq("last_farm_id", farmId).eq("subscribe", 1));
            for (SysAccountMultilevel sysAccountMultilevel : list) {
               WeChatMessage.sendMsg(now,"充电预警",basePigpen1.getBuildName(),basePigpen.getBuildName().substring(basePigpen1.getBuildName().length()),sysAccountMultilevel.getWechatId());
                WeChatMessage2.sendMsg(now,"充电预警",basePigpen1.getBuildName(),basePigpen.getBuildName().substring(basePigpen1.getBuildName().length()),sysAccountMultilevel.getWechatId());
                sysAccountMultilevel.setSubscribe(0);
                sysAccountMultilevelService.updateById(sysAccountMultilevel);
            }
            WebsocketWorkerUtil.sendWarningMessage(farmId,String.format("%s 高温预警",basePigpen.getBuildName()));
            pushAlarm(terminaCode +terminalPortCode,2,envData);
        }
        if (splitStatus[1] == 1){
            portWarningInfo.setContent(String.format("%s 漏电预警",basePigpen.getBuildName()));
            portWarningInfo.setWarningType(3);
            portWarningInfoService.save(portWarningInfo);

            List<SysAccountMultilevel> list = sysAccountMultilevelService.list(new QueryWrapper<SysAccountMultilevel>().eq("last_farm_id", farmId).eq("subscribe", 1));
            for (SysAccountMultilevel sysAccountMultilevel : list) {
                WeChatMessage.sendMsg(now,"充电预警",basePigpen1.getBuildName(),basePigpen.getBuildName().substring(basePigpen1.getBuildName().length()),sysAccountMultilevel.getWechatId());
                WeChatMessage2.sendMsg(now,"充电预警",basePigpen1.getBuildName(),basePigpen.getBuildName().substring(basePigpen1.getBuildName().length()),sysAccountMultilevel.getWechatId());

                sysAccountMultilevel.setSubscribe(0);
                sysAccountMultilevelService.updateById(sysAccountMultilevel);
            }
            WebsocketWorkerUtil.sendWarningMessage(farmId,String.format("%s 漏电预警",basePigpen.getBuildName()));
            pushAlarm(terminaCode +terminalPortCode,1,envData);
        }
    }

    private void askCmdActuatorV1(String askText, ChannelHandlerContext ctx,  String[] dataArray) throws IOException {
        //芯片id/设备编码
        String cmd = dataArray[1];
        switch (cmd) {
            case "1":
                //心跳
                getHear(askText, dataArray, ctx,1);
                break;
            case "2":
                //上传数据
                getChuanGanData(askText, dataArray, ctx);
                break;
            case "3":
                //充电前后功率
                savePower(askText, dataArray, ctx);
                break;
            case "4":
                //充电中电流
                saveElectric(askText, dataArray, ctx);
                break;
            case "5":
                //充电前电流
                saveBeforeElectric(askText, dataArray, ctx);
                break;
            default:
                log.error(String.format("未知指令 --> %s", askText));
                answerCmd("hm+4+1+end", ctx);
        }
    }

    private synchronized void saveBeforeElectric(String askText, String[] dataArray, ChannelHandlerContext ctx) {
        String ans = "hm+5+1+end";
        answerCmd(ans,ctx);
        String gateWayCode = dataArray[2];
        String  terminalCode = dataArray[3];
        String terminalPortCode = dataArray[4];
        String num = dataArray[5];
        String eleData = dataArray[6];
        Date now = new Date();

        try {
            PortChangeData portChangeData = portChangeDataService.getOne(new QueryWrapper<PortChangeData>().eq("terminal_port_code", gateWayCode + terminalCode + terminalPortCode).eq("num", num));
            if (ObjectUtils.isEmpty(portChangeData)) {
                portChangeData = new PortChangeData();
                portChangeData.setNum(Integer.parseInt(num));
                portChangeData.setCreateTime(now);
                portChangeData.setGatwayCode(gateWayCode);
                portChangeData.setTerminalCode(gateWayCode+terminalCode);
                portChangeData.setTerminalPortCode(gateWayCode+terminalCode+terminalPortCode);
                portChangeData.setBeforeElectricCurrent(eleData);
                portChangeDataService.save(portChangeData);
            }else {
                portChangeData.setBeforeElectricCurrent(eleData);
                portChangeDataService.updateById(portChangeData);
            }
        }catch (Exception e){
            log.error(String.format("点位查询失败--> %s" ,askText));
            log.error(e);
        }
    }

    private synchronized void saveElectric(String askText, String[] dataArray, ChannelHandlerContext ctx) {
        String ans = "hm+4+1+end";
        answerCmd(ans,ctx);
        String gateWayCode = dataArray[2];
        String  terminalCode = dataArray[3];
        String terminalPortCode = dataArray[4];
        String num = dataArray[5];
        String eleData = dataArray[6];
        Date now = new Date();

        try {
            PortChangeData portChangeData = portChangeDataService.getOne(new QueryWrapper<PortChangeData>().eq("terminal_port_code", gateWayCode + terminalCode + terminalPortCode).eq("num", num));
            if (ObjectUtils.isEmpty(portChangeData)) {
                portChangeData = new PortChangeData();
                portChangeData.setNum(Integer.parseInt(num));
                portChangeData.setCreateTime(now);

                portChangeData.setGatwayCode(gateWayCode);
                portChangeData.setTerminalCode(gateWayCode+terminalCode);
                portChangeData.setTerminalPortCode(gateWayCode+terminalCode+terminalPortCode);
                portChangeData.setElectricCurrent(eleData);

                portChangeDataService.save(portChangeData);
            }else {
                portChangeData.setElectricCurrent(eleData);
                portChangeDataService.updateById(portChangeData);
            }
        }catch (Exception e){
            log.error(String.format("点位查询失败--> %s" ,askText));
            log.error(e);
        }
    }


    public  String reverseWithComma(String input) {
        String[] parts = input.split(",");
        List<String> partList = Arrays.asList(parts);
        Collections.reverse(partList);
        StringBuilder reversedBuilder = new StringBuilder();
        for (int i = 0; i < partList.size(); i++) {
            reversedBuilder.append(partList.get(i));
            if (i < partList.size() - 1) {
                reversedBuilder.append(",");
            }
        }
        return reversedBuilder.toString();
    }

    private synchronized void savePower(String askText, String[] dataArray, ChannelHandlerContext ctx) {
        String ans = "hm+3+1+end";
        answerCmd(ans,ctx);
        String gateWayCode = dataArray[2];
        String  terminalCode = dataArray[3];
        String terminalPortCode = dataArray[4];
        String num = dataArray[5];
        int[] splitPower = Arrays.stream(dataArray[6].split(",")).mapToInt(Integer::parseInt).toArray();
        int[] splitBeforePower = Arrays.stream(dataArray[7].split(",")).mapToInt(Integer::parseInt).toArray();
        Date now = new Date();

        try {
            PortChangeData portChangeData = portChangeDataService.getOne(new QueryWrapper<PortChangeData>().eq("terminal_port_code", gateWayCode + terminalCode + terminalPortCode).eq("num", num));
            if (ObjectUtils.isEmpty(portChangeData)) {
                portChangeData = new PortChangeData(gateWayCode + terminalCode + terminalPortCode,gateWayCode + terminalCode ,gateWayCode,
                        splitPower[0],splitPower[1],splitPower[2],
                        splitBeforePower[0],splitBeforePower[1],splitBeforePower[2],
                        now,Integer.parseInt(num));
                portChangeDataService.save(portChangeData);
            }else {
                portChangeData.setActivePower( splitPower[0]);
                portChangeData.setReactivePower( splitPower[1]);
                portChangeData.setApparentPower( splitPower[2]);
                portChangeData.setBeforeActivePower(splitBeforePower[0]);
                portChangeData.setBeforeReactivePower(splitBeforePower[1]);
                portChangeData.setBeforeApparentPower(splitBeforePower[2]);
                portChangeDataService.updateById(portChangeData);
            }
        }catch (Exception e){
            log.error(String.format("点位查询失败--> %s" ,askText));
            log.error(e);
        }
    }
    private void getHear(String askText,String[] dataArray, ChannelHandlerContext ctx,int version) throws IOException {
        /**
         * 接口中只需要定义你要用到的函数或者公共变量，不需要的可以不定义
         * 映射libadd.so里面的函数，注意类型要匹配
         */

        String ans = "hm+1+1+end";
        answerCmd(ans,ctx);
        String gateWayCode = dataArray[2];
       String  terminalCode = version == 1 ? dataArray[3] : "1";

        TerminalPort terminalPort = new TerminalPort();
        terminalPort.setStatus(1);
        terminalPortService.update(terminalPort,new UpdateWrapper<TerminalPort>().like("device_code",gateWayCode + terminalCode));
        Terminal terminal = new Terminal();
        terminal.setStatus(1);
        terminalService.update(terminal,new UpdateWrapper<Terminal>().eq("device_code",gateWayCode + terminalCode));
        Gateway gateway = new Gateway();
        gateway.setStatus(1);
        gatewayService.update(gateway,new UpdateWrapper<Gateway>().eq("device_code",gateWayCode ));

        HeartInfo heartInfo1 = new HeartInfo(new Date(), gateWayCode + terminalCode, gateWayCode, askText);
        heartInfoService.save(heartInfo1);

    }


    private void getChuanGanData(String askText,String[] dataArray, ChannelHandlerContext ctx) throws IOException {
        String ans = "hm+2+1+end";
        answerCmd(ans,ctx);
        //hm+2+867699060005643+1+1+2207+0+0+4+1,0,20+0,0,0+v1.0+21+end
        String gateWayCode = dataArray[2];
        String  terminalCode = dataArray[3];
        String terminalPortCode = dataArray[4];
        String voltage = getNum(dataArray[5]);
        String electriCurrent = getNum(dataArray[6]);
        String temp = getNum(dataArray[7]);
        String leakageValue = getNum(dataArray[8]);
        Date now = new Date();
        int[] splitPower = Arrays.stream(dataArray[9].split(",")).mapToInt(Integer::parseInt).toArray();
        int[] splitStatus =Arrays.stream(dataArray[10].split(",")).mapToInt(Integer::parseInt).toArray();
        EnvData envData = new EnvData(gateWayCode+terminalCode+terminalPortCode,gateWayCode+terminalCode,gateWayCode,
                voltage,electriCurrent,temp, leakageValue,
                splitPower[0],splitPower[1],splitPower[2],
                splitStatus[0],splitStatus[1],splitStatus[2],
                askText,now);
        envDataService.save(envData);
        //更新状态
//        try {
            TerminalPort deviceCode = terminalPortService.getOne(new QueryWrapper<TerminalPort>().eq("device_code", gateWayCode + terminalCode + terminalPortCode));
            if (ObjectUtils.isEmpty(deviceCode)){
                log.info(String.format("无端口设备--> %s" ,askText));
                return;
            }
            deviceCode.setVoltage(voltage);
            deviceCode.setElectricCurrent(electriCurrent);
            deviceCode.setTemp(temp);
            deviceCode.setLeakageValue(leakageValue);
            deviceCode.setActivePower( splitPower[0]);
            deviceCode.setReactivePower(splitPower[1]);
            deviceCode.setApparentPower(splitPower[2]);
            deviceCode.setHeightTempWarning( splitStatus[0]);
            deviceCode.setChargingWarning( splitStatus[1]);
            deviceCode.setLeakageWarning( splitStatus[2]);
            deviceCode.setUpdateTime(now);
            deviceCode.setStatus(1);
            terminalPortService.updateById(deviceCode);
            //添加报警
            saveWarning(gateWayCode,terminalCode,terminalPortCode,deviceCode,splitStatus,now,envData);
//        }catch (Exception e){
//            log.error(String.format("端口设备查询失败--> %s" ,askText));
//            log.error(e);
//        }

    }

    private void saveWarning(String gateWayCode,String terminaCode,String terminalPortCode ,TerminalPort terminalPort,int[] splitStatus,Date now,EnvData envData) throws IOException {
        if (splitStatus[0] == 0 && splitStatus[1] == 0 &&splitStatus[2] == 0 )
            return;
        Integer farmId = terminalPort.getFarmId();
        Integer locationId = terminalPort.getLocationId();
        BaseFarm baseFarm = baseFarmService.getById(farmId);
        BasePigpen basePigpen = basePigpenService.getById(locationId);

        if (ObjectUtils.isEmpty(baseFarm)){
            log.info(String.format("无小区数据--> %s" ,terminalPort.toString()));
            return;
        }
        if (ObjectUtils.isEmpty(basePigpen)){
            log.info(String.format("无栋舍数据--> %s" ,terminalPort.toString()));
            return;
        }
        BasePigpen basePigpen1= basePigpenService.getById(basePigpen.getOther2().split(",")[1]);
        PortWarningInfo portWarningInfo = new PortWarningInfo();
        portWarningInfo.setGatwayCode(gateWayCode);

        portWarningInfo.setTerminalCode(gateWayCode+terminaCode);
        portWarningInfo.setTerminalPortCode(gateWayCode+ terminaCode +terminalPortCode);
        portWarningInfo.setLocationId(locationId);
        portWarningInfo.setFarmId(farmId);
        portWarningInfo.setWarningType(1);
        portWarningInfo.setCreateTime(now);
        if (splitStatus[0] == 1){

            portWarningInfo.setContent(String.format("%s 高温预警",basePigpen.getBuildName()));
            portWarningInfo.setWarningType(1);
            portWarningInfoService.save(portWarningInfo);

            List<SysAccountMultilevel> list = sysAccountMultilevelService.list(new QueryWrapper<SysAccountMultilevel>().eq("last_farm_id", farmId).eq("subscribe", 1));
            for (SysAccountMultilevel sysAccountMultilevel : list) {
                WeChatMessage.sendMsg(now,"高温预警",basePigpen1.getBuildName(),basePigpen.getBuildName().substring(basePigpen1.getBuildName().length()),sysAccountMultilevel.getWechatId());
                WeChatMessage2.sendMsg(now,"高温预警",basePigpen1.getBuildName(),basePigpen.getBuildName().substring(basePigpen1.getBuildName().length()),sysAccountMultilevel.getWechatId());
                sysAccountMultilevel.setSubscribe(0);
                sysAccountMultilevelService.updateById(sysAccountMultilevel);
            }
            //
            WebsocketWorkerUtil.sendWarningMessage(farmId,String.format("%s 高温预警",basePigpen.getBuildName()));
            //推送事件
            pushAlarm(terminaCode +terminalPortCode,2,envData);
        }

        if (splitStatus[1] == 1){
            portWarningInfo.setContent(String.format("%s 充电预警",basePigpen.getBuildName()));
            portWarningInfo.setWarningType(2);
            portWarningInfoService.save(portWarningInfo);
            List<SysAccountMultilevel> list = sysAccountMultilevelService.list(new QueryWrapper<SysAccountMultilevel>().eq("last_farm_id", farmId).eq("subscribe", 1));
            for (SysAccountMultilevel sysAccountMultilevel : list) {
                WeChatMessage.sendMsg(now,"充电预警",basePigpen1.getBuildName(),basePigpen.getBuildName().substring(basePigpen1.getBuildName().length()),sysAccountMultilevel.getWechatId());
                WeChatMessage2.sendMsg(now,"充电预警",basePigpen1.getBuildName(),basePigpen.getBuildName().substring(basePigpen1.getBuildName().length()),sysAccountMultilevel.getWechatId());
                sysAccountMultilevel.setSubscribe(0);
                sysAccountMultilevelService.updateById(sysAccountMultilevel);
            }
            WebsocketWorkerUtil.sendWarningMessage(farmId,String.format("%s 充电预警",basePigpen.getBuildName()));
            pushAlarm(terminaCode +terminalPortCode,12,envData);
        }
        if (splitStatus[2] == 1){
            portWarningInfo.setContent(String.format("%s 漏电预警",basePigpen.getBuildName()));
            portWarningInfo.setWarningType(3);
            portWarningInfoService.save(portWarningInfo);
            List<SysAccountMultilevel> list = sysAccountMultilevelService.list(new QueryWrapper<SysAccountMultilevel>().eq("last_farm_id", farmId).eq("subscribe", 1));
            for (SysAccountMultilevel sysAccountMultilevel : list) {
                WeChatMessage.sendMsg(now,"漏电预警",basePigpen1.getBuildName(),basePigpen.getBuildName().substring(basePigpen1.getBuildName().length()),sysAccountMultilevel.getWechatId());
                WeChatMessage2.sendMsg(now,"漏电预警",basePigpen1.getBuildName(),basePigpen.getBuildName().substring(basePigpen1.getBuildName().length()),sysAccountMultilevel.getWechatId());
                sysAccountMultilevel.setSubscribe(0);
                sysAccountMultilevelService.updateById(sysAccountMultilevel);
            }
            WebsocketWorkerUtil.sendWarningMessage(farmId,String.format("%s 漏电预警",basePigpen.getBuildName()));
            pushAlarm(terminaCode +terminalPortCode,1,envData);
        }
    }

    private void pushAlarm(String deviceId,Integer errorCode, EnvData envData) throws IOException {
        AlarmInfoVO alarmInfoVO = new AlarmInfoVO();
        alarmInfoVO.setDevice_id(deviceId);
        alarmInfoVO.setError_code(errorCode);
        switch (errorCode){
            case 2:
                alarmInfoVO.setError_value(envData.getTemp());
                break;
            case 1:
                alarmInfoVO.setError_value(envData.getLeakageValue());
                break;
            default :
//                alarmInfoVO.setError_value(envData.getActivePower());
                System.out.println("充电报警");
                break;
        }

        alarmInfoVO.setFrequency(50);
        alarmInfoVO.setLeakage(envData.getLeakageValue());
        alarmInfoVO.setVolt_a(envData.getVoltage());
        alarmInfoVO.setCurr_a(envData.getElectricCurrent());
        alarmInfoVO.setTemp_a(envData.getTemp());
        alarmInfoVO.setPower_a(envData.getActivePower());
        ArrayList<AlarmInfoVO> list1 = new ArrayList<>();
        list1.add(alarmInfoVO);
        ElePostUtils.heartPost(BASE_URL + ALARM_URL, envData.getGatwayCode(),list1);
    }

    private String getNum(String  num){
        return String.format("%.1f", Double.parseDouble(num) / 10.0);
    }


    //应答
    public void answerCmd(String answerText, ChannelHandlerContext ctx) {
        log.info(String.format("应答数据--->%s",answerText));
        ctx.writeAndFlush(Unpooled.copiedBuffer(answerText.getBytes()));
    }

    //检查无效耳标
    public boolean checkValidEarmark(String earmark) {
        if (earmark.trim().equalsIgnoreCase("ffffffffffffffff") || earmark.trim().equalsIgnoreCase("0000000000000000")) {
            return true;
        } else {
            return false;
        }
    }

    //拆分粘包数据
    public JSONArray parseAskCmdPackage(String text) {
        String key = "end";
        Pattern pattern = Pattern.compile(key);
        Matcher matcher = pattern.matcher(text);
        int count = 0;
        while (matcher.find()) {
            count++;
        }
        JSONArray dataJa = new JSONArray();
        if (count == 1) {
            dataJa.add(text);
        } else {
            for (int a = 0; a < count; a++) {
                int p1 = text.indexOf("end");
                dataJa.add(text.substring(0, p1 + 3));
                text = text.substring(p1 + 3, text.length());
            }
        }
        return dataJa;
    }
}
