package com.hboxs.serialport;

import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.util.Log;

import com.hboxs.serialport.frame.CommandFrame;
import com.hboxs.serialport.frame.ReadCommandFrame;
import com.hboxs.serialport.util.Order;

import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

/**
 * 串口发送队列
 */
public class SerialPortSendQueue {
    private final static String TAG = "SerialPortSendQueue";

    //讀的數據
    private static LinkedList<Order> sMessageListRead = new LinkedList<>();
    private static boolean isSendSuccess = true;

    //寫的數據
    private static LinkedList<Order> sMessageListWrite = new LinkedList<>();


    /**
     * 线程名称
     */
    private final static String THREAD_NAME = BuildConfig.APPLICATION_ID + ".SERIAL_PORT_SEND_QUEUE";
    /**
     * 发送命令的handler线程
     */
    private static HandlerThread mSendCommandHandlerThread;
    private static SendCommandHandler mHandler;

    /**
     * 静态常量
     */
    private final static SerialPortSendQueue queue = new SerialPortSendQueue();

    /**
     * 获取当前正在发送的命令
     *
     * @return
     */
    public static CommandFrame getCurrentFrame() {
        return currentFrame;
    }

    private static CommandFrame currentFrame;

    /**
     * 不允许创建对象
     */
    private SerialPortSendQueue() {
        mSendCommandHandlerThread = new HandlerThread(THREAD_NAME);
    }

    /**
     * 开始
     */
    private void startThread() {
        if (!mSendCommandHandlerThread.isAlive()) {
            mSendCommandHandlerThread.start();
            mHandler = new SendCommandHandler();
            //mHandler被干掉的情况。
//            isSendSuccess = true;
            Log.w(TAG, "Queue Thread has been started.");
        }
    }

    /**
     * 开启读list的线程
     */
    public static void startReadListThread() {
        Log.d(TAG, "SerialPortSendQueue startReadListThread 开启读list线程---------------");
        try {
            if (sMessageListWrite.size() == 0) {
                if (sMessageListRead.size() != 0) {
                    if (isSendSuccess == true) {
                        isSendSuccess = false;
                        synchronized (SerialPortSendQueue.class) {
                            sendOrderMessage(sMessageListRead.getFirst());
                        }
                    }
                }
            } else {
                if (isSendSuccess == true) {
                    isSendSuccess = false;
                    synchronized (SerialPortSendQueue.class) {
                        sendOrderMessage(sMessageListWrite.getFirst());
                    }
                }
            }
            Thread.sleep(10);
        } catch (Exception e) {
            Log.e(TAG, "读取数据失败", e);
            e.printStackTrace();
            isSendSuccess = true;
        }
    }

    private static void sendOrderMessage(Order order) {
        if (order != null) {
            Message message = new Message();
            message.what = order.getWhat();
            message.obj = order.getCommand();
            Bundle bundle = new Bundle();
            bundle.putString("address", order.getMaddress());
            message.setData(bundle);
            queue.sendMessage(message);
            Log.d(TAG, "run: 发送指令");
        } else {
            Log.d(TAG, "run: order 为空");
            isSendSuccess = true;
        }
    }

    /**
     * 结束
     */
    private void stopThread() {
        if (mSendCommandHandlerThread.isAlive()) {
            mSendCommandHandlerThread.quit();
        } else {
            Log.w(TAG, "Queue Thread not started yet.");
        }
    }

    /**
     * 发送命令消息
     *
     * @param message 命令消息
     */
    private void sendMessage(Message message) {
        if (mHandler != null) {

            mHandler.sendMessage(message);
        } else {
            throw new RuntimeException("发送命令handler未启动");
        }
    }


    /**
     * 开始队列
     */
    public static void start() {
        queue.startThread();
    }

    /**
     * 结束队列
     */
    public static void stop() {
        queue.stopThread();
    }

    /**
     * 清除所有消息
     */
    public static void clear() {
        if (mHandler != null) {
            // mHandler.removeCallbacksAndMessages(null);
        }
    }


    /**
     * 发送命令120
     *
     * @param command 命令帧
     */
    public static void sendCommand(CommandFrame command) {
        Message message = new Message();
        message.obj = command;
//        queue.sendMessage(message);
//        sMessageList.add(sMessageList.size(), message);
    }

    /**
     * 发送命令
     *
     * @param command 命令帧
     * @param id      消息id
     */
    public static void sendCommand(CommandFrame command, int id, String address) {

        //   Log.d(TAG, "收到命令：" + id + "  线程： " + Thread.currentThread().getName());
//        Message message = new Message();
//        message.what = id;
//        message.obj = command;
//        Bundle bundle = new Bundle();
//        bundle.putString("address", address);
//        message.setData(bundle);
//        queue.sendMessage(message);
        synchronized (SerialPortSendQueue.class) {


            if (sMessageListRead.size() >= 15) {
                sMessageListRead.clear();
            }
            if (sMessageListWrite.size() >= 15) {
                sMessageListWrite.clear();
            }
            Order order = new Order(id, address, command);
            if (command instanceof ReadCommandFrame) {
                if (!sMessageListRead.contains(order)) {
                    sMessageListRead.add(order);
                }
            } else {
                if (!sMessageListWrite.contains(order)) {
                    sMessageListWrite.add(order);
                }
            }
            Log.d(TAG, "read list -->" + sMessageListRead.size());
        }
    }

    /**
     * 设置收到数据
     */
    public static CommandFrame setReceived() {
        return queue.received();
    }

    private CommandFrame received() {
        if (mHandler == null) {
            throw new RuntimeException("发送命令handler未启动");
        }
        CommandFrame frame = mHandler.frame;
        mHandler.isReceived = true;
        return frame;
    }

    /**
     * 发送命令的handler
     */
    private class SendCommandHandler extends Handler {
        /**
         * 最大等待次数
         */
        private final static int MAX_WAIT_TIMES = 10;
        /**
         * 最大超时重试次数，0为不重试
         */
        private final static int MAX_TIMEOUT_RETRY_TIMES = 1;
        // 是否接收到数据
        private boolean isReceived;
        private CommandFrame frame;

        SendCommandHandler() {
            super(mSendCommandHandlerThread.getLooper());
            if (!mSendCommandHandlerThread.isAlive()) {
                throw new RuntimeException("发送命令队列线程尚未建立");
            }
        }

        @Override
        public void handleMessage(Message msg) {

            Log.d(TAG, "处理命令：" + msg.what + "  线程： " + Thread.currentThread().getName());
            // 读取命令
            frame = (CommandFrame) msg.obj;
            currentFrame = frame;
            Bundle data = msg.getData();
            String address = data.getString("address");
            frame.setId(msg.what);
            frame.setAddress(address);
            // 初始化参数
            isReceived = false;
            boolean success = true;
            int times = 0;
            int retry = 0;
            // TODO 发送命令
            Log.d(TAG, "发送命令：" + msg.what + "  线程： " + Thread.currentThread().getName());
            SerialPortManager.getInstance().sendCommandFrame(frame, "" + msg.what);

            // 轮询等待
            while (!isReceived) {
                // 增加轮询次数
                times++;
                try {
                    // 单次等待时间，越小轮询越快
                    Thread.sleep(30);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                if (!isReceived && times >= MAX_WAIT_TIMES) {
                    // 等待超时
                    if (retry < MAX_TIMEOUT_RETRY_TIMES) {
                        // 进入重试
                        times = 0;
                        retry++;
                        // TODO 发送命令
                        Log.d(TAG, "重发命令：" + msg.what + "  线程： " + Thread.currentThread().getName());
                        SerialPortManager.getInstance().sendCommandFrame(frame, msg.what + "");
                    } else {
                        // 重试超过最大次数，跳出循环
                        success = false;
                        break;
                    }
                }
            }
            Log.d(TAG, "完成命令：" + msg.what + " 状态：" + (success ? "正常" : "超时") + "  线程： " + Thread.currentThread().getName());

            synchronized (SerialPortSendQueue.class) {


                if (success) {
                    if (frame instanceof ReadCommandFrame) {
//                    sMessageListRead.remove(0);
                        sMessageListRead.pollFirst();
                    } else {
//                    sMessageListWrite.remove(0);
                        sMessageListWrite.pollFirst();
                    }
                }
                if (sMessageListRead.size() >= 10) {
                    sMessageListRead.clear();
                }
                if (sMessageListWrite.size() >= 10) {
                    sMessageListWrite.clear();
                }

                isSendSuccess = true;
            }
        }
    }
}
