package com.huimv.eartag.server;

import com.alibaba.fastjson.JSONArray;
import com.huimv.eartag.service.IDataService;
import com.huimv.eartag.service.IDeviceService;
import com.huimv.eartag.utils.DateUtil2;
import com.huimv.eartag.utils.RegexUtil;
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.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.text.ParseException;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Project : huimv.shiwan
 * @Package : com.huimv.biosafety.uface.controller
 * @Description : TODO
 * @Version : 1.0
 * @Author : ZhuoNing
 * @Create : 2020-12-25
 **/
@ChannelHandler.Sharable
@Component
@Slf4j
public class EartagServerHandler2 extends ChannelInboundHandlerAdapter {
    @Autowired
    private IDataService dataService;
    @Autowired
    private DateUtil2 dateUtil;
    @Autowired
    private RegexUtil regexUtil;
    @Autowired
    private IDeviceService deviceService;
    @Value("${data.input.flow}")
    private Integer dataInputFlow;
    @Value("${data.test.input}")
    private Integer dataTestInput;
    private StringBuilder askTextSb = null;
    private int num = 0;

    //
    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);
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
//        ctx.writeAndFlush("111");
        if(askTextSb.toString().indexOf("end") != -1){
            // 业务处理入口 //
            handleClientEartagMessage(askTextSb.toString(),ctx);
            askTextSb.delete(0,askTextSb.length());
            num = 0;
        }
    }

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

    /**
     * @Method      : handleClientMessage
     * @Description : 处理请求小心
     * @Params      : [clientAskText, ctx]
     * @Return      : void
     * 
     * @Author      : ZhuoNing
     * @Date        : 2022/3/28       
     * @Time        : 17:36
     */
    private void handleClientEartagMessage(String clientAskText, ChannelHandlerContext ctx) throws ParseException {
        clientAskText = clientAskText.replaceAll("\r","").replaceAll("\n","");
        System.out.println("### 服务端接收数据 >>" + clientAskText);
        //TEST-saveRawData()
        if(dataTestInput == 1){
            deviceService.saveRawData(clientAskText);
        }

        //{}
        int countPlus = regexUtil.countPlus(clientAskText);
        if (countPlus < 4) {
            System.out.println("当前数据为不完整数据，故丢弃.>>" + clientAskText);
        } else {
            //{拆分粘包数据}
            JSONArray askJa = getPerData(clientAskText);
            for (int a = 0; a < askJa.size(); a++) {
                String askText = askJa.getString(a);
                //TEST-saveRawData()
//                deviceService.saveRawData(askText);
//                if (dataInputFlow == 1) {
//                    //{处理请求内容}
//                    handleAskText(askText, ctx);
//                } else {
                    //{处理请求内容2}
                    handleAskText2(askText, ctx);
//                }
            }
        }
    }

    /**
     * @Method : handleAskText2
     * @Description :
     * @Params : [askText, ctx]
     * @Return : void
     * @Author : ZhuoNing
     * @Date : 2022/3/23
     * @Time : 18:08
     */
    private void handleAskText2(String askText, ChannelHandlerContext ctx) throws ParseException {
        String[] dataArray = askText.split("\\+");
        String cmdHeader = dataArray[0];
        //芯片id/设备编码
        String idCode = dataArray[1];
        String cmd = dataArray[2];
        Map map = new HashMap();
        map.put("askText", askText);
        if (cmdHeader.trim().equalsIgnoreCase("hm")) {
            //采集器应答数据
            if (cmd.trim().equalsIgnoreCase("0")) {
                //不需要处理
                System.out.println("==>命令0");
            } else if (cmd.trim().equalsIgnoreCase("1")) {
                System.out.println("==>命令1请求 askText>>" + askText.trim());
                //处理获取设备编码命令
                //{读取设备编码}
                String deviceCode = dataService.getDeviceCodeByChipId(idCode);
                log.info("获取设备编码结果,芯片id>>" + idCode + " ,deviceCode>>" + deviceCode);
                if (deviceCode != null) {
                    String answer = "hm+1+0+" + deviceCode + "+123+8+end";
                    log.info(">>命令1设备编码-应答数据>>" + answer);
                    ctx.writeAndFlush(Unpooled.copiedBuffer(answer.getBytes()));
                } else {
                    log.error("检测到未注册的采集器设备,已舍弃请求.");
                }
            } else if (cmd.trim().equalsIgnoreCase("2")) {
                System.out.println("==>命令2请求 askText>>" + askText);
                if (dataService.isEffectiveDevice(idCode)) {
                    //处理服务器时间命令
                    String answer = "hm+2+" + dateUtil.getNowText() + "+4+end";
                    log.info(">>命令2服务器时间-应答数据>>" + answer);
                    ctx.writeAndFlush(Unpooled.copiedBuffer(answer.getBytes()));
                }else {
                    System.out.println("##获取服务器时间-无效设备编码 idCode=" + idCode);
                }
            } else if (cmd.trim().equalsIgnoreCase("3")) {
                System.out.println("==>命令3请求 askText>>" + askText);
                //处理心跳包命令
                //{设备心跳应答}
                if (dataService.isEffectiveDevice(idCode)) {
                    String answer = "hm+3+6+end";
                    log.info(">>命令3心跳包-应答数据>>" + answer);
                    ctx.writeAndFlush(Unpooled.copiedBuffer(answer.getBytes()));

                    //{发送到设备处理消息队列}
                    dataService.sendDeviceMQ(map);
                    log.info(">>发送设备心跳数据消息到MQ."+map);
                } else {
                    System.out.println("##心跳包-无效设备编码(" + idCode+")，请求拒绝。");
                }
            } else if (cmd.trim().equalsIgnoreCase("4")) {
                System.out.println("==>命令4请求 askText>>" + askText);
                //处理设备环境温度命令
                //{设备环境温度应答}
                if (dataService.isEffectiveDevice(idCode)) {
                    String answer = "hm+4+7+end";
                    log.info(">>命令4环境温度-应答数据>>" + answer);
                    ctx.writeAndFlush(Unpooled.copiedBuffer(answer.getBytes()));

                    //{发送到设备处理消息队列}
                    dataService.sendDeviceMQ(map);
                    log.info(">>发送设备环境温度数据消息到MQ."+map);
                } else {
                    System.out.println("##环境温度-无效设备编码(" + idCode+")，请求拒绝。");
                }
            } else {
                System.out.println("==>未知命令");
                log.error(">>当前数据为非法数据>>" + askText);
            }
        } else if (cmdHeader.trim().equalsIgnoreCase("zj")) {
            System.out.println("==>耳标命令请求 askText>>"+askText);
            //耳标应答数据（不需要应答）
            if (checkValidEarmark(cmd)) {
                log.error(">>舍弃掉未配置耳标号的耳标，" + askText + "");
            } else {
                //{检查设备是否在处于工作状态或待机状态}
//                if (dataService.isWorkStatusDevice(idCode)) {
                if (dataService.isEffectiveDevice(idCode)) {
                    //{发送到耳标处理消息队列}
                    dataService.sendEartagMQ(map);
                    log.info(">>发送耳标数据消息到MQ."+map);
                }else{
                    System.out.println("无效设备编码 idCode="+idCode);
                }
            }
        } else {
            System.out.println("==>未知命令");
            log.error("##当前请求数据为非法数据>>" + askText);
        }
    }

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

    /**
     * @Method : handleAskText
     * @Description : 处理请求内容
     * @Params : [askText, ctx]
     * @Return : void
     * @Author : ZhuoNing
     * @Date : 2022/3/23
     * @Time : 17:36
     */
    private void handleAskText(String askText, ChannelHandlerContext ctx) throws ParseException {
        String[] dataArray = askText.split("\\+");
        String cmdHeader = dataArray[0];
        //芯片id/设备编码
        String idCode = dataArray[1];
        String cmd = dataArray[2];
        //{先判断是否已经注册，未注册的非法设备都过滤掉}
        boolean validStatus = dataService.isValidDevice(cmdHeader, idCode, cmd);
        System.out.println("## validStatus>>" + validStatus);
        if (validStatus) {
            System.out.println("-->1");
            //{处理应答}
            String answer = dataService.getDeviceAnswer(cmdHeader, cmd, idCode);
            System.out.println("-->2");
            if (answer != null) {
                System.out.println("-->2.1");
                log.info("###应答响应>>" + answer + "\n");
                ctx.writeAndFlush(Unpooled.copiedBuffer(answer.getBytes()));
                System.out.println("-->2.2");
            } else {
                System.out.println("-->2.3");
                log.info("###应答数据>>" + answer + "，不需要应答。\n");
            }
            System.out.println("-->3");
            //{发送消息异步处理}
            dataService.sendBizMQ(cmdHeader, cmd, askText);
            System.out.println("-->4");
        }
    }

    //    @Override
//    public void channelRead_old2(ChannelHandlerContext ctx, Object msg) throws Exception {
//        ByteBuf data = (ByteBuf) msg;
//        String clientAskText = data.toString(CharsetUtil.UTF_8);
////        clientAskText = clientAskText.replaceAll("\r","").replaceAll("\n","");
//        System.out.println("### 服务端接收数据 >>" + clientAskText);
//        //TEST-saveRawData()
////        deviceService.saveRawData(clientAskText);
//        //{}
//        int countPlus = regexUtil.countPlus(clientAskText);
//        if (countPlus < 4) {
//            System.out.println("当前数据为不完整数据，故丢弃.>>" + clientAskText);
//        } else {
//            //--处理客户端请求数据
////            System.out.println("000拆分粘包之前数据 clientAskText>>"+clientAskText);
//            //{拆分粘包数据}
//            JSONArray askJa = getPerData(clientAskText);
//            for (int a = 0; a < askJa.size(); a++) {
//                //先判断是否再所有牧场的集合当中，未登记都过滤掉；
////                cacheService.isValidDevice(deviceCode);
//
//                //{处理客户端请求数据}
//                String answer = dataService.handleClientAsk(askJa.getString(a));
//                System.out.println("## 返回应答>>" + answer);
//                if (answer != null) {
//                    log.info("###应答响应>>" + answer + "\n");
//                    ctx.writeAndFlush(Unpooled.copiedBuffer(answer.getBytes()));
//                } else {
//                    log.info("###应答数据>>" + answer + "，不需要应答。\n");
//                }
//            }
//        }
//    }

    //    @Override
//    public void channelRead_old1(ChannelHandlerContext ctx, Object msg) throws Exception {
//        ByteBuf data = (ByteBuf) msg;
//        String clientAskText = data.toString(CharsetUtil.UTF_8);
//        System.out.println("### 服务端接收数据 >>" + clientAskText);
//        if (clientAskText.length() <= 18) {
//            System.out.println("当前数据为不完整数据，故丢弃.>>" + clientAskText);
//        } else {
//            //--处理客户端请求数据
////            String answer = eartagDataService.handleClientAsk(clientAskText, ctx);
//////            String answer = eartagDataService.handleClientAsk(clientAsk, ctx);
////            if (answer != null) {
////                log.info("###应答响应>>" + answer + "\n");
////                ctx.writeAndFlush(Unpooled.copiedBuffer(answer.getBytes()));
////            } else {
////                log.info("###应答数据>>" + answer + "，不需要应答。\n");
////            }
////            System.out.println("000拆分粘包之前数据 clientAskText>>"+clientAskText);
////            --拆分粘包数据
//            JSONArray askJa = getPerData(clientAskText);
//            for (int a = 0; a < askJa.size(); a++) {
//                //--处理客户端请求数据
//                String answer = dataService.handleClientAsk(askJa.getString(a), ctx);
////            String answer = eartagDataService.handleClientAsk(clientAsk, ctx);
//                if (answer != null) {
//                    log.info("###应答响应>>" + answer + "\n");
//                    ctx.writeAndFlush(Unpooled.copiedBuffer(answer.getBytes()));
//                } else {
//                    log.info("###应答数据>>" + answer + "，不需要应答。\n");
//                }
//            }
//        }
//    }

    //拆分粘包数据
    public JSONArray getPerData(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;
    }

}
