package cn.myapps.runtime.log.aspect.instruction;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

public class LogInstructionExecutor {
    /**
     * 指令执行器实例
     */
/*
    private final static Map<String, String> METHON_MAP = new HashMap<String, String>();

    private final static Map<String, String> USER_INFO = new HashMap<String, String>();

    private final static Map<String, String> DEPT_INFO = new HashMap<String, String>();

 */

    private static LogInstructionExecutor INSTANCE = null;

    private ThreadLocal<Queue<LogInstruction>> queueHolder = new ThreadLocal<Queue<LogInstruction>>();

    /**
     * 任务队列
     */
    private Queue<LogInstruction> queue = new ConcurrentLinkedQueue<>();

    private static Object LOCK = new Object();

    private boolean isWaitForJobs = false;

    /**
     * 获取指令执行器实例
     * @return
     */
    public static LogInstructionExecutor getInstance(){
        if(INSTANCE==null){
            synchronized (LogInstructionExecutor.class) {
                INSTANCE = new LogInstructionExecutor();
                INSTANCE.logSchedule();
            }
        }
        return INSTANCE;
    }


    /**
     * 添加一个指令到指令队列
     * @param instruction
     * 		指令对象
     */
    public void put(LogInstruction instruction){
        kickThread();
        queue.add(instruction);
    }

    /**
     * 获取指令队列
     * @return
     */
    private Queue<LogInstruction> getQueue(){
        queue = queueHolder.get();
        if(queue==null){
            queue = new ConcurrentLinkedQueue<LogInstruction>();
            queueHolder.set(queue);
        }

        return queue;
    }

    /**
     * 清空指令队列
     */
    public void clear() {
        Queue<LogInstruction> queue = queueHolder.get();
        if(queue != null){
            queue.clear();
        }
    }

    /**
     * 唤醒任务队列派发线程
     */
    private void kickThread() {
        synchronized (LOCK) {
            LOCK.notifyAll();
        }
    }

    /**
     * 执行队列中的指令
     * @throws Exception
     */
    public void  execute() throws Exception{
//        Queue<LogInstruction> queue = getQueue();
        LogInstruction instruction = null;
        while((instruction = queue.poll())!=null){
            instruction.run();
        }
    }

    private void logSchedule(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){
                    synchronized (LOCK){
                        while (!queue.isEmpty()){
                            try {
                                execute();
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                        if(queue.isEmpty()){
                            isWaitForJobs = true;
                        }else {
                            isWaitForJobs = false;
                        }
                    }

                    if (isWaitForJobs){
                        synchronized (LOCK){
                            try {
                                LOCK.wait();
                            } catch (InterruptedException e) {
                            }
                        }
                    }
                }
            }
        }).start();
    }
}
