package org.example.socket;

import com.ctc.wstx.util.StringUtil;
import io.netty.channel.*;
import org.example.background.service.MakeInfoService;
import org.example.utils.CommonConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.net.SocketAddress;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @author zjb
 * @since 2023-12-11 10:31:26
 */
@Component
@EnableAsync
@ChannelHandler.Sharable
public class BootNettySocketChannelInboundHandler extends ChannelInboundHandlerAdapter {

    private final Logger log =  LoggerFactory.getLogger(this.getClass());

    @Resource
    private MakeInfoService makeInfo;

    private Map<String, ChannelHandlerContext> ctxMap = new ConcurrentHashMap<String, ChannelHandlerContext>(16);


    /**
     * 	从客户端收到新的数据时，这个方法会在收到消息时被调用
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object frame) {
//      int[] ints = makeInfo.sendEnergyGetDevId50();
        String result = makeInfo.convertPlaintext((byte[]) frame);
            if(result.equals("-1")){
            System.out.println("CRC校验错误，收到的数据不完整或错误");
        }else{
            System.out.println("客户端发送:"+result);
            Integer res = makeInfo.convertTextToData(result, getClientIP(ctx));
                if(res > 0) {
                    //发送补充指令
                    //发送第二条指令
                    int[] data2 = makeInfo.sendEnergyGetDevId50();
                    ChannelFuture channelFuture1 = ctx.channel().writeAndFlush(data2);
                    channelFuture1.addListener((ChannelFutureListener) future2 -> {
                        if (future2.isSuccess()) {
                            sendEnergyMessages(data2);
                        } else {
                            System.out.println("第二条指令发送失败");
                        }
                    });
                }
            }
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        // 客户端断开连接的处理逻辑
        System.out.println("客户端断开连接");
        ctxMap.remove(getClientIP(ctx));
        super.channelInactive(ctx);
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("客户端(重新)连接：" + ctx.channel().remoteAddress());
        ctxMap.put(getClientIP(ctx),ctx);
        super.channelActive(ctx);
    }


    /**
     * 	客户端与服务端 断连时执行 channelInactive方法之后执行
     */
    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        ctxMap.remove(getClientIP(ctx));
        super.channelUnregistered(ctx);
    }

    /**
     * 	当出现 Throwable 对象才会被调用，即当 Netty 由于 IO 错误或者处理器在处理事件时抛出的异常时
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
//      ctxMap.remove(getClientIP(ctx));
        super.exceptionCaught(ctx, cause);
    }

    @Scheduled(cron = "0 0 */1 * * *") //每小时的第0分钟第0秒
//    @Scheduled(fixedRate = 10000) //10秒
    private void sendIntervals() {
        int[] data = makeInfo.sendEnergyMessage();
            ChannelHandlerContext ctx = ctxMap.get(CommonConfig.energy1);
            if(!StringUtils.isEmpty(ctx)) {
                ChannelFuture channelFuture = ctx.channel().writeAndFlush(data);
                // 添加监听器，检查发送是否成功
                channelFuture.addListener((ChannelFutureListener) future1 -> {
                if(future1.isSuccess()) {
                    sendEnergyMessages(data);
                }else{
                    System.out.println("第一条指令发送失败");
                }
                });
            }else{
                System.out.println("ip为"+CommonConfig.energy1+"的客户端不在线。无法传递指令");
            }
    }

    public void sendEnergyMessages(int [] data){
        System.out.println("成功发送指令:");
        for(int num = 0; num < data.length; num++){
            if (num == data.length - 1) {
                System.out.print(Integer.toHexString(data[num]));
                System.out.print("\n");
            }else {
                System.out.print(Integer.toHexString(data[num]) + " ");
            }
        }
    }

    public String getClientIP(ChannelHandlerContext ctx){
        String ip = ctx.channel().remoteAddress().toString();
        return ip.substring(1, ip.indexOf(":"));
    }

}
