package com.zd.laboratory.socket.runner;

import cn.hutool.json.JSONUtil;
import com.zd.common.core.utils.SpringUtils;
import com.zd.common.core.utils.StringUtils;
import com.zd.laboratory.socket.constant.JXCTPacket;
import com.zd.laboratory.socket.constant.SocketTypes;
import com.zd.laboratory.socket.service.BaseRouter;
import com.zd.laboratory.socket.service.SocketService;
import com.zd.laboratory.socket.vo.TransmissionVo;
import com.zd.laboratory.utils.CRCCHECK;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.Socket;
import java.net.SocketException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @author dgs
 * socket服务器配置类
 */
public class TCPServer implements Runnable {

    private static final Logger log = LoggerFactory.getLogger(TCPServer.class);

    public static Map<String, OutputStream> cacheMap = new ConcurrentHashMap<>();

    private Socket socket;


    public TCPServer(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        /*if(!SocketRunner.whitelist.contains(socket.getInetAddress().toString())){
            try {
                socket.close();
            } catch (IOException e) {
            }
            return;
        }*/
        // 设置连接超时90秒
        try {
            socket.setSoTimeout(200000);
            log.info("客户 - " + socket.getRemoteSocketAddress() + " -> 机连接成功");
            while (true) {
                handle();
            }
        } catch (SocketException e) {
            log.info("Socket异常： " + socket.getRemoteSocketAddress());
            log.error("Socket异常： " + e.getMessage());
        } catch (IOException e) {
            log.error("Socket异常： " + e.getMessage());
        } finally {
            try {
                if (!socket.isClosed()) {
                    log.info("客户 - " + socket.getRemoteSocketAddress() + " -> 链接中断");
                    socket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private void handle() throws IOException {

        StringBuilder ret = new StringBuilder();

        // 解析二进制数据
        BufferedInputStream bs = new BufferedInputStream(socket.getInputStream());

        DataInputStream dis = new DataInputStream(bs);

        byte[] bytes = new byte[1];
        while (dis.read(bytes) != -1){
            ret.append(bytesToHexString(bytes) + " ");
            if(dis.available() == 0){
                break;
            }
        }

        String data = ret.toString();
        if(StringUtils.isEmpty(data)){
            throw new IOException("释放DDoS");
        }

        log.info("接收数据：" + data + "," + socket.getRemoteSocketAddress());

        SocketService socketService = SpringUtils.getBean(SocketService.class);

        if(data.startsWith(SocketTypes.SENSOR_PREFIX)){
            socketService.setSensorData(data);
        }else if(data.startsWith(SocketTypes.RELAY_PREFIX)){
            analyticRelayData(data);
        }else if(data.startsWith(SocketTypes.LOCK_PREFIX)){
            // 柜锁第一次连接上报采集器编号绑定连接
            cabinetLockData(data);
        }else {
            // 柜锁发送指令回调未携带采集器编号
            socketService.setCabinetLockData(socket, data);
        }

    }

    private void cabinetLockData(String data) {
        try {
            data = data.replace(" ", "").toUpperCase();
            cacheMap.put(data, socket.getOutputStream());
            log.warn("化学品智能柜锁连接，采集器编号：" + data);
        }catch (Exception e){
            log.error(e.toString());
        }
    }

    private void analyticRelayData(String data) {
        try {
            /*final byte b[] = new byte[512];
            int len = socket.getInputStream().read(b);//读取数据
            if (len > 0) {
                byte[] datas = new byte[len];
                System.arraycopy(b, 0, datas, 0, len);
                String data = SocketUtils.formatBytes(datas, " ");*/
                JXCTPacket packet = new JXCTPacket(data.replace(" ", "").toUpperCase());
                BaseRouter baseRouter = BaseRouter.routerMap.get(packet.order);
                if (baseRouter == null) {
                    log.error("不识别指令：" + packet.order);
                    return;
                }
                cacheMap.put(packet.deviceNumber, socket.getOutputStream());
                String sendBody = baseRouter.routePacket(packet);
                //解析数据
                if (sendBody != null) {
                    //log.info(packet.deviceNumber + " 下发:" + sendBody);
                    //socket.getOutputStream().write(SocketUtils.str2byte(sendBody));
                }
            //}
        }catch (Exception e){
            e.printStackTrace();
            log.error(e.toString());
        }

    }

    /**
     * 将二进制转换成16进制
     */
    public static String bytesToHexString(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            String hex = Integer.toHexString(0xFF & bytes[i]);
            if(hex.length() == 1){
                sb.append("0");
            }
            sb.append(hex);
        }
        return sb.toString();
    }

    /**
     * 将16进制转换为二进制
     *
     */
    public static byte[] parseHexStr2Byte(String hexStr) {
        if (hexStr.length() < 1)
            return null;
        byte[] result = new byte[hexStr.length() / 2];
        for (int i = 0; i < hexStr.length() / 2; i++) {
            int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
            int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2),
                    16);
            result[i] = (byte) (high * 16 + low);
        }
        return result;
    }

    // 二进制转字符串
    public static String byte2hex(byte[] b) {
        StringBuffer sb = new StringBuffer();
        String tmp = "";
        for (int i = 0; i < b.length; i++) {
            tmp = Integer.toHexString(b[i] & 0XFF);
            if (tmp.length() == 1){
                sb.append("0" + tmp);
            }else{
                sb.append(tmp);
            }

        }
        return sb.toString();
    }

    public static void main(String[] args) throws Exception {
        // fe dc 固定头
        // 11  去头尾 的字节长度
        // 04 dd 80 b6 3c 17   第一位表示是几路继电器
        // 00 功能码

        // 00 00 位号
        // 15 0a
        // 0e 0e
        // 13 1c

        // e0 41  校验码
        // ac db  规定尾

//        String str = "40";
//        System.out.println(Integer.parseInt(str, Character.FORMAT));
//
//        byte[] a = TCPServer.parseHexStr2Byte(str);
//
//        Integer num = Integer.parseInt(str, Character.FORMAT);
//        System.out.println(Integer.toBinaryString(num));
        // gb2312   gb18030
//        String out = TCPServer.bytesToHexString("二维码内容".getBytes("gbk"));
//        System.out.println(out);
//
//
//        String qrCode = "68 74 74 70 73 3A 2F 2F 75 2E 77 65 63 68 61 74 2E 63 6F 6D 2F 4D 46 77 41 75 6D 75 63 2D 41 6F 52 5F 4C 64 59 49 48 64 38 43 5F 45";
//        byte[] b = TCPServer.parseHexStr2Byte(qrCode.replaceAll(" ", ""));
//
//        System.out.println(TCPServer.byte2hex(b));

        String str = "fe dc 01 78 99 4c 6c 61 88 00 02 64 30 03 00 34 00 00 00 00 00 00 00 00 00 00 01 2d 00 00 01 55 00 01 88 f6 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00";

        TransmissionVo transmissionVo = new TransmissionVo(str);

        System.out.println(JSONUtil.toJsonStr(transmissionVo));
    }
}
