package com.hh.arome.helper.Serial;


import android.app.Activity;
import android.os.Build;

import com.aill.androidserialport.SerialPort;
import com.hh.arome.utlis.log.AppLogUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

/**
 * 串口管理类
 */
public class SerialManage<A> {
    String[] SerialPaths=new String[]{"/dev/smd11","/dev/smd4","/dev/smdcntl8","/dev/smd21","/dev/smd1","/dev/smd6","/dev/smd8","/dev/smdcntl0","/dev/smd3","/dev/smd7","/dev/smd36","/dev/smd2","/dev/smd5","/dev/smd22","/dev/smd_pkt_loopback","/dev/ttyHSL3","/dev/ttyHSL1","/dev/ttyHSL0","/dev/ttyHSL2","/dev/ttyHSL3","/dev/ttyHSL1","/dev/ttyHSL0","/dev/ttyHSL2"};
    private static SerialManage instance;
    private static SerialPort serialPort;
    private ScheduledExecutorService scheduledExecutor;//线程池 同一管理保证只有一个
    private SerialHandle serialHandle;//串口连接 发送 读取处理对象
    private Queue<String> queueMsg = new ConcurrentLinkedQueue<String>();//线程安全到队列
    private ScheduledFuture sendStrTask;//循环发送任务
    private boolean isConnect = false;//串口是否连接
    //虚拟串口路径
    private int YOUR_VID= 0x152A;
    private int YOUR_PID = 0x880F;

    private SerialManage() {
        scheduledExecutor = Executors.newScheduledThreadPool(8);//初始化8个线程
    }

    public static SerialManage getInstance() {
        if (instance == null) {
            synchronized (SerialManage.class) {
                if (instance == null) {
                    instance = new SerialManage();
                }
            }
        }
        return instance;
    }

    /**
     * 获取线程池
     *
     * @return
     */
    public ScheduledExecutorService getScheduledExecutor() {
        return scheduledExecutor;
    }

    /**
     * 串口初始化
     *
     * @param serialInter
     */
    public void init(SerialInter serialInter) {
        if (serialHandle == null) {
            serialHandle = new SerialHandle();
            startSendTask();
        }
        serialHandle.addSerialInter(serialInter);
    }

    /**
     * 打开串口
     */
    public void open(Activity activity) {
        String[] DevicesPath=new SerialPortFinder().getAllDevicesPath();
        String path= "";
        if (Build.MODEL.indexOf("F2")!=-1){
            path="/dev/ttyS4";
        }else {
            path="/dev/ttyHSL2";
        }
        AppLogUtils.e("---------open  path   "+path);
//        if (Config.getAuthenticationBean().getData().get(0).isUseLinkage()){
            isConnect = serialHandle.open(path, 9600, true);//设置地址，波特率，开启读取串口数据
//        }else {
//            if (!Config.getAuthenticationBean().getData().get(0).getUseSerialPort().equals("RS232")){
//               return;
//            }
//            isConnect = serialHandle.open(path, 9600, true);//设置地址，波特率，开启读取串口数据
//        }

    }

    /**
     * 打开串口
     */
    public void open(String path) {
        isConnect = serialHandle.open(path, 9600, true);//设置地址，波特率，开启读取串口数据
    }
    /**
     * 发送指令
     *
     * @param msg
     */
    public void send(String msg) {
        /*
         此处没有直接使用 serialHandle.send(msg); 方法去发送指令
         因为 某些硬件在极短时间内只能响应一个指令,232通讯一次发送多个指令会有物理干扰，
         让硬件接收到指令不准确；所以 此处将指令添加到队列中，排队执行，确保每个指令一定执行.
         若不相信可以试试用serialHandle.send(msg)方法循环发送10个不同的指令，看看10个指令
         的执行结果。
         */
        if (queueMsg!=null){
            queueMsg.offer(msg);//向队列添加指令
        }
    }

    /**
     * 关闭串口
     */
    public void colse() {
        if (serialHandle!=null){
            serialHandle.close();//关闭串口
        }
    }

    //启动发送发送任务
    private void startSendTask() {
        cancelSendTask();//先检查是否已经启动了任务 ？ 若有则取消
        //每隔100毫秒检查一次 队列中是否有新的指令需要执行
        sendStrTask = scheduledExecutor.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                if (!isConnect) return;//串口未连接 退出
                if (serialHandle == null) return;//串口未初始化 退出
                String msg = queueMsg.poll();//取出指令SerialInter
                if (msg == null || "".equals(msg)) return;//无效指令 退出
                serialHandle.send(msg);//发送指令
            }
        }, 0, 100, TimeUnit.MILLISECONDS);
    }

    //取消发送任务
    private void cancelSendTask() {
        if (sendStrTask == null) return;
        sendStrTask.cancel(true);
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        sendStrTask = null;
    }

    /**
     * 找出两个list的不同元素
     * @param list1
     * @param list2
     * @return
     */
    private static List<String> getDiffByNative(List<String> list1, List<String> list2){
        List<String> resultList = new ArrayList<>();
        for (String s1 :list1) {
            if(!list2.contains(s1)){
                resultList.add(s1);
            }
        }
        for (String s2:list2) {
            if(!list1.contains(s2)){
                resultList.add(s2);
            }
        }
        return resultList;
    }
}
