package com.xydl.cac.serialport;

import com.fazecast.jSerialComm.SerialPort;
import com.xydl.cac.model.StaticVariable;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.PreDestroy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Service
@Slf4j
public class SerialPortServer {

    @Value("${cac.warnport.name}")
    public String portname;

    @Value("${cac.warnport.intervaltime:60}")
    public Integer intervaltime;

    @Value("${cac.warnport.warntime:5}")
    public Integer warntime;

    public SerialPort currentPort;//当前可用串口
    public long LastWarningTime;//最后一次硬接点告警时间
    public boolean started = false;

    byte[] openbuffer = new byte[]{00, (byte) 0xf1, (byte) 0xff};//发送串口告警
    byte[] stopbuffer = new byte[]{00, (byte) 0x01, (byte) 0xff};//关闭串口告警

    public void discoverSerialPort() {
        if (currentPort == null) {
            List<SerialPort> serialPortList = new ArrayList<>();
            SerialPort[] commPorts = SerialPort.getCommPorts();
            if (commPorts != null && commPorts.length > 0) {
                serialPortList = Arrays.asList(commPorts);
                for (SerialPort port : serialPortList) {
                    log.info("获取串口: " + port.getSystemPortName());
                    String systemPortName = port.getSystemPortName();
                    if (systemPortName != null) {
                        if (systemPortName.startsWith(portname)) {
                            currentPort = port;
                            log.info("获取到硬接点告警串口: " + port.getSystemPortName());
                        }
                    }
                }
            }
        } else {
            log.error("硬接点串口存在！");
        }
    }

    public void closeSerialPort() {
        if (currentPort != null) {
            log.info("断开串口成功！");
            currentPort.closePort();
        } else {
            log.error("断开串口失败，没有对应的硬接点告警串口！");
        }
    }


    //发送数据到串口
    @Async
    public void sendData() {
        if (!started) {
            started = true;
            if (openSerialPort()) {
                SerialPort port = currentPort;
                if (port != null) {
                    long l = System.currentTimeMillis();
                    if (LastWarningTime == 0) {
                        LastWarningTime = l;
                    } else {
                        if (l - LastWarningTime <= (intervaltime * 1000)) {
                            started = false;
                            log.info("告警频繁，取消告警！");
                            return;
                        }
                    }
                    LastWarningTime = l;
                    log.info("开始发送告警！");
                    port.writeBytes(openbuffer, openbuffer.length);
                    int seconds = 0;
                    while (StaticVariable.shutdown == 0 && seconds < warntime) {
                        try {
                            Thread.sleep(1000);
                            seconds++;
                        } catch (Exception ignore) {
                        }
                    }
                    log.info("开始关闭告警！");
                    port.writeBytes(stopbuffer, stopbuffer.length);

                }
            }
            started = false;
            closeSerialPort();
        }
    }


    public Boolean openSerialPort() {
        discoverSerialPort();
        if (currentPort != null) {
            if (currentPort.isOpen()) {
                log.info("硬接点告警串口已经打开！");
                return true;
            } else {
                int baudRate = 9600; // 波特率
                int parity = SerialPort.EVEN_PARITY; // 校验位
                int dataBits = 8; // 数据位
                int stopBits = SerialPort.ONE_STOP_BIT; // 停止位
                try {
                    boolean setComResult = currentPort.setComPortParameters(baudRate, dataBits, stopBits, parity); // 设置参数
                    boolean setComTimes = currentPort.setComPortTimeouts(SerialPort.TIMEOUT_READ_SEMI_BLOCKING, 20000, 0); // 设置超时
                    if (setComResult && setComTimes) {
                        currentPort.addDataListener(new DataListener(currentPort.getSystemPortName()));
                    }
                    boolean b = currentPort.openPort();
                    if (b) {
                        log.info("打开硬接点告警串口成功！");
                        return true;
                    } else {
                        currentPort = null;
                        log.error("打开串口失败！");
                        return false;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    currentPort = null;
                    log.error("打开串口失败" + e.getMessage());
                    return false;
                }
            }
        } else {
            log.error("打开串口失败,找不到硬接点串口！");
            return false;
        }
    }

    @PreDestroy
    private void stop() {
        closeSerialPort();
    }

}
