package com.youchain.Netty;

import com.youchain.basicdata.domain.LampLog;
import com.youchain.basicdata.repository.LampLogRepository;
import com.youchain.basicdata.service.impl.LampLogServiceImpl;
import com.youchain.utils.RedisUtils;
import com.youchain.utils.SpringContextHolder;
import com.youchain.utils.StringUtils;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;

import java.net.InetSocketAddress;
@Slf4j
public class NettyUtils {

    public static final String button_1="0001";
    public static final String button_2="0002";
    public static final String button_3="0003";
    public static final String button_4="0004";

    private static final String button_on="0001";
    private static final String button_off="0000";

    public static final String light_1="0005";
    public static final String light_2="0006";
    public static final String light_3="0007";
    public static final String light_4="0008";


    private static final String light_off="0000";
    private static final String light_on="0001";

    private static final String light_fast="0002";

    private static final String light_slow="0003";
    /**
     * 灯光熄灭
     * @param ip 按钮盒ip
     * @param index 位置码
     * @param lamp_log_id 日志id 如果是null为新增
     */
    public static void light_off(String ip,String index,Long lamp_log_id){
        Channel channel= getChannel(ip);
        //4位通讯帧号
        //4位通讯协议
        //4位数据长度（在这后面的总长度）
        //2位设备地址 01
        //2位功能码 06 写入单个数据
        //4位寄存器地址 （按钮/灯）
        //4位数据 （按钮 0没有被按下，1按钮被按下）（指示灯 0灭，1亮，2快闪，3慢闪）
        String content="0001"+"0000"+"0006"+"01"+"06"+index+light_off;
        writeToClient(lamp_log_id,content,channel,"灯光熄灭");
    }
    /**
     * 灯光常亮
     * @param ip 按钮盒ip
     * @param index 位置码light_x
     * @param lamp_log_id 日志id 如果是null为新增
     */
    public static void light_on(String ip,String index,Long lamp_log_id){
        Channel channel= getChannel(ip);
        //4位通讯帧号
        //4位通讯协议
        //4位数据长度（在这后面的总长度）
        //2位设备地址 01
        //2位功能码 06 写入单个数据
        //4位寄存器地址 （按钮/灯）
        //4位数据 （按钮 0没有被按下，1按钮被按下）（指示灯 0灭，1亮，2快闪，3慢闪）
        String content="0001"+"0000"+"0006"+"01"+"06"+index+light_on;
        writeToClient(lamp_log_id,content,channel,"灯光常亮");
    }
    /**
     * 灯光快闪
     * @param ip 按钮盒ip
     * @param index 位置码
     * @param lamp_log_id 日志id 如果是null为新增
     */
    public static void light_on_fast_flicker(String ip,String index,Long lamp_log_id){
        Channel channel= getChannel(ip);
        //4位通讯帧号
        //4位通讯协议
        //4位数据长度（在这后面的总长度）
        //2位设备地址 01
        //2位功能码 06 写入单个数据
        //4位寄存器地址 （按钮/灯）
        //4位数据 （按钮 0没有被按下，1按钮被按下）（指示灯 0灭，1亮，2快闪，3慢闪）
        String content="0001"+"0000"+"0006"+"01"+"06"+index+light_fast;
        writeToClient(lamp_log_id,content,channel,"灯光快闪");
    }

    /**
     * 灯光慢闪
     * @param ip 按钮盒ip
     * @param index 位置码
     * @param lamp_log_id 日志id 如果是null为新增
     */
    public static void light_on_slow_flicker(String ip,String index,Long lamp_log_id){
        Channel channel= getChannel(ip);
        //4位通讯帧号
        //4位通讯协议
        //4位数据长度（在这后面的总长度）
        //2位设备地址 01
        //2位功能码 06 写入单个数据
        //4位寄存器地址 （按钮/灯）
        //4位数据 （按钮 0没有被按下，1按钮被按下）（指示灯 0灭，1亮，2快闪，3慢闪）
        String content="0001"+"0000"+"0006"+"01"+"06"+index+light_slow;
        writeToClient(lamp_log_id,content,channel,"灯光慢闪");
    }


    /**
     * 按钮释放
     * @param ip 按钮盒ip
     * @param index 位置码button_x
     * @param lamp_log_id 日志id 如果是null为新增
     */
    public static void button_off(String ip,String index,Long lamp_log_id){
        Channel channel= getChannel(ip);
        //4位通讯帧号
        //4位通讯协议
        //4位数据长度（在这后面的总长度）
        //2位设备地址 01
        //2位功能码 06 写入单个数据
        //4位寄存器地址 （按钮/灯）
        //4位数据 （按钮 0没有被按下，1按钮被按下）（指示灯 0灭，1亮，2快闪，3慢闪）
        String content="0001"+"0000"+"0006"+"01"+"06"+index+button_off;
        writeToClient(lamp_log_id,content,channel,"按钮释放");
    }

    /**
     * 按钮按下
     * @param ip 按钮盒ip
     * @param index 位置码
     * @param lamp_log_id 日志id 如果是null为新增
     */
    public static void button_on(String ip,String index,Long lamp_log_id){
        Channel channel= getChannel(ip);
        //4位通讯帧号
        //4位通讯协议
        //4位数据长度（在这后面的总长度）
        //2位设备地址 01
        //2位功能码 06 写入单个数据
        //4位寄存器地址 （按钮/灯）
        //4位数据 （按钮 0没有被按下，1按钮被按下）（指示灯 0灭，1亮，2快闪，3慢闪）
        String content="0001"+"0000"+"0006"+"01"+"06"+index+button_on;
        writeToClient(lamp_log_id,content,channel,"按钮按下");

    }


    public static void sendMsg(String ip,String content,Long lamp_log_id){
        Channel channel= getChannel(ip);
        writeToClient(lamp_log_id,content,channel,"测试");
    }

    public static Channel getChannel(String ip){
        for (Channel client : ServerListenerHandler.clients) {
            String devce_ip =((InetSocketAddress)client.remoteAddress()).getAddress().getHostAddress();
            if(ip.equals(devce_ip)){
                return  client;
            }
        }
        return null;
    }



    public static void writeToClient(final Long lamp_log_id,final String sendStr, Channel channel, final String mark) {
        //加载redis
        //000000000006010300010008
        //000100000006010600060000

        if("000000000006010300010008".equals(sendStr)){
            log.info("回写心跳,执行一次"+sendStr);
            ReawriteToClient(lamp_log_id,sendStr,channel,mark);
        }else{
            log.info("其他数据,执行两次"+sendStr);
            ReawriteToClient(lamp_log_id,sendStr,channel,mark);
            try{
                Thread.sleep(100);
            }catch (Exception e){

            }
            ReawriteToClient(lamp_log_id,sendStr,channel,mark);
        }

    }


    public static void ReawriteToClient(final Long lamp_log_id,final String sendStr, Channel channel, final String mark) {
        //加载redis
        RedisUtils redisUtils = SpringContextHolder.getBean(RedisUtils.class);
        if(channel==null){
            //"设备IP无效";
           if (lamp_log_id!=null){
               redisUtils.set(String.valueOf(lamp_log_id),"设备IP无效");
           }
            return;
        }
        try {
            ByteBuf bufff = Unpooled.buffer();//netty需要用ByteBuf传输
            bufff.writeBytes(HexTools.hexString2Bytes(sendStr));//对接需要16进制
            channel.writeAndFlush(bufff).addListener(new ChannelFutureListener() {
                @Override
                public void operationComplete(ChannelFuture future) throws Exception {
                    StringBuilder sb = new StringBuilder();
                    if(!StringUtils.isEmpty(mark)){
                        sb.append("【").append(mark).append("】");
                    }
                    if (future.isSuccess()) {
                        log.info(sb.toString()+"回写成功"+sendStr);
                       if (lamp_log_id!=null){
                           redisUtils.set(String.valueOf(lamp_log_id),sb.toString()+"回写成功"+sendStr);
                       }
                    } else {
                        log.error(sb.toString()+"回写失败"+sendStr);
                        if (lamp_log_id!=null){
                            redisUtils.set(String.valueOf(lamp_log_id),sb.toString()+"回写失败"+sendStr);
                        }
                    }
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
            log.error("调用通用writeToClient()异常"+e.getMessage());
            if (lamp_log_id!=null){
                redisUtils.set(String.valueOf(lamp_log_id), "调用通用writeToClient()异常"+e.getMessage());
            }
        }
    }
}
