package cn.superdesk.uniorder.common.queue.block;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Description: 阻塞任务队列 单例
 * @Author: linjinyu
 * @CreateDate: 2021/9/10 下午1:45
 * @UpdateUser: linjinyu
 * @UpdateDate: 2021/9/10 下午1:45
 * @UpdateRemark: 修改内容
 * @Version: 1.0
 */
@Slf4j
public class BlockTaskQueue {

	private String TAG = "BlockTaskQueue";

	private AtomicInteger mAtomicInteger = new AtomicInteger();

	// 阻塞队列
	private final BlockingQueue<TaskInterface> mTaskQueue = new PriorityBlockingQueue<>();

	private BlockTaskQueue() {
	}

	// 单例模式
	private static class BlockTaskQueueHolder {
		private final static BlockTaskQueue INSTANCE = new BlockTaskQueue();
	}

	public static BlockTaskQueue getInstance() {
		return BlockTaskQueueHolder.INSTANCE;
	}

	/**
	 * 插入时 因为每一个Task都实现了comparable接口 所以队列会按照Task复写的compare()方法定义的优先级次序进行插入
	 * 当优先级相同时,使用AtomicInteger原子类自增 来为每一个task 设置sequence,
	 * sequence的作用是标记两个相同优先级的任务入队的次序
	 */
	public <T extends TaskInterface> int add(T task) {

		if (!mTaskQueue.contains(task)) {

			// 顺序自增
			task.setSequence(mAtomicInteger.incrementAndGet());
			mTaskQueue.add(task);

			log.info(TAG, "\n add task " + task.toString());
		}

		return mTaskQueue.size();
	}


	public <T extends TaskInterface> void remove(T task) {

		if (mTaskQueue.contains(task)) {
			log.info(TAG, "\n" + "task has been finished. remove it from task queue");
			mTaskQueue.remove(task);
		}

		if (mTaskQueue.size() == 0) {
			mAtomicInteger.set(0);
		}
	}

	/**
	 * 任务队列-任务出列-非阻塞
	 *
	 * @return
	 */
	public TaskInterface poll() {
		return mTaskQueue.poll();
	}

	/**
	 * 任务队列-任务出列-阻塞
	 *
	 * @return
	 * @throws InterruptedException
	 */
	public TaskInterface take() throws InterruptedException {
		return mTaskQueue.take();
	}

	// 任务队列-任务清空
	public void clear() {
		mTaskQueue.clear();
	}

	// 任务队列-长度
	public int size() {
		return mTaskQueue.size();
	}
}
