package com.bonus.tcp.server.handle;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.shaded.com.google.common.collect.Maps;
import com.bonus.common.entity.tcp.TcpDataVo;
import com.bonus.tcp.server.config.BootNettyChannel;
import com.bonus.tcp.server.config.BootNettyChannelCache;
import com.bonus.tcp.smartIdentify.service.impl.TcpDataService;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import com.bonus.common.core.utils.SpringUtils;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.Map;

/**
 * I/O数据读写处理类
 * 蚂蚁舞
 */
@ChannelHandler.Sharable
public class BootNettyChannelInboundHandlerAdapter extends ChannelInboundHandlerAdapter {

    public TcpDataService service = SpringUtils.getBean(TcpDataService.class);

    public static  int data_type=41;
    public static  int warn_type=51;
    /**
     * 注册时执行
     */
    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        //注册通道
        super.channelRegistered(ctx);
        System.out.println("--channelRegistered--" + ctx.channel().id().toString());
    }

    /**
     * 离线时执行
     */
    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        //通道离线
        super.channelUnregistered(ctx);
        String channel = ctx.channel().id().toString();
        String  devCode=service.getDevCodeByChannel(channel);
        service.downLoadStatus(channel);
        BootNettyChannelCache.remove("server:" + devCode);
        System.out.println("--channelUnregistered--" + ctx.channel().id().toString());
    }

    /**
     * 从客户端收到新的数据时，这个方法会在收到消息时被调用
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        try {
            if (msg == null) {
                return;
            }
            //转成String
            String data = (String) msg;
            //替换掉 换行 和 空格
            data = data.replaceAll("\r|\n", "");
            //获取通道ID 并打印

            JSONObject json= JSON.parseObject(data);
            //返回数据内容
            Map<String,Object> map= Maps.newHashMap();
            int type=json.getIntValue("type");
            String channel = ctx.channel().id().toString();
            String channelId = ctx.channel().id().toString();
            if(data_type==type){
                JSONArray devArray=json.getJSONArray("device");
                JSONObject object=devArray.getJSONObject(0);
                channelId=object.getString("id");
                String dl=object.getString("quantity");
                String jl=object.getString("data");
                map.put("type",42);
                service.updateDeviceInfo(channelId,dl,jl);
            }else if(warn_type==type){
                 map.put("type",52);
                 map.put("id",channelId);
                 channelId=json.getString("id");
                 int  report=json.getIntValue("report");
                //进行告警存储
                service.insertWarnInfo(channelId,type,report,data);

            }
            System.err.println("通道号--->" + channelId );
            System.err.println("data-->" + data);
            BootNettyChannel b = BootNettyChannelCache.get("server:" + channelId);
            if (b == null) {
                //更新通道
                  service.updateTcpChannelId(channel,channelId,type);
                //创建通道
                BootNettyChannel bnc = new BootNettyChannel();
                bnc.setChannel(ctx.channel());
                //设置通道编码
                bnc.setCode("server:" + channelId);
                bnc.setReport_last_data(data);
                //保存通道
                BootNettyChannelCache.save("server:" + channelId, bnc);
            } else {
                b.setReport_last_data(data);
            }

            map.put("s",1);
            String res=JSON.toJSONString(map);
            //回写给客户端
            ctx.writeAndFlush(Unpooled.buffer().writeBytes((res).getBytes()));
        } catch (Exception e) {
            System.out.println("channelRead--" + e.toString());
        }
    }

    /**
     * 从客户端收到新的数据、读取完成时调用
     */
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws IOException {
        System.out.println("channelReadComplete");
        ctx.flush();
    }

    /**
     * 当出现 Throwable 对象才会被调用，即当 Netty 由于 IO 错误或者处理器在处理事件时抛出的异常时
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws IOException {
        System.out.println("exceptionCaught");
        //打印错误内容
        cause.printStackTrace();
        //获取到这个通道
        BootNettyChannel bnc = BootNettyChannelCache.get("server:" + ctx.channel().id().toString());
        if (bnc != null) {
            //移除掉
            BootNettyChannelCache.remove("server:" + ctx.channel().id().toString());
        }
        ctx.close();//抛出异常，断开与客户端的连接
    }

    /**
     * 客户端与服务端第一次建立连接时 执行
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception, IOException {
        //调用原始方法
        super.channelActive(ctx);
        ctx.channel().read();
        //获取到IP地址
        InetSocketAddress inSocket = (InetSocketAddress) ctx.channel().remoteAddress();
        String clientIp = inSocket.getAddress().getHostAddress();
        //此处不能使用ctx.close()，否则客户端始终无法与服务端建立连接
        System.out.println("channelActive:" + clientIp + ctx.name());
    }

    /**
     * 客户端与服务端 断连时 执行
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception, IOException {
        super.channelInactive(ctx);
        //获取到IP
        InetSocketAddress inSocket = (InetSocketAddress) ctx.channel().remoteAddress();
        String clientIp = inSocket.getAddress().getHostAddress();
        System.out.println("channelInactive:" + clientIp);

        //获取到通道
        BootNettyChannel bnc = BootNettyChannelCache.get("server:" + ctx.channel().id().toString());
        if (bnc != null) {
            //移除
            BootNettyChannelCache.remove("server:" + ctx.channel().id().toString());
        }
        ctx.close(); //断开连接时，必须关闭，否则造成资源浪费，并发量很大情况下可能造成宕机
    }

    /**
     * 服务端当read超时, 会调用这个方法
     */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception, IOException {
        super.userEventTriggered(ctx, evt);
        //获取到通道
        InetSocketAddress inSocket = (InetSocketAddress) ctx.channel().remoteAddress();
        //获取到IP
        String clientIp = inSocket.getAddress().getHostAddress();

        ctx.close();//超时时断开连接
        System.out.println("userEventTriggered:" + clientIp);
    }

}
