package com.maniu.http;

import android.util.Log;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 管理请求队列
 */
public class ThreadManager {
    private static ThreadManager threadManager = new ThreadManager();
    //请求队列
    private LinkedBlockingQueue<Runnable> mQueue = new LinkedBlockingQueue<>();
    //线程池
    private ThreadPoolExecutor threadPoolExecutor;
    //重试队列  延时的功能
    private DelayQueue<Delayed> delayedsQueue = new DelayQueue<>();

    private ThreadManager(){
        threadPoolExecutor = new ThreadPoolExecutor(3, 10, 15,
                TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(4), new RejectedExecutionHandler() {
            @Override
            public void rejectedExecution(Runnable runnable, ThreadPoolExecutor threadPoolExecutor) {
                mQueue.add(runnable);
            }
        });
        threadPoolExecutor.execute(runnable);
        threadPoolExecutor.execute(faildRunable);
    }

    public static ThreadManager getInstance(){
        return threadManager;
    }

    public void addTask(Runnable runnable){
        if(runnable!=null){
            mQueue.add(runnable);
        }
    }


    /**
     * 将失败的请求线程加入到重试队列中
     * @param httpTask
     */
    public void addFailedTask(HttpTask httpTask){
        if(httpTask == null){
            return;
        }
        httpTask.setDelayeTime(3000);
        delayedsQueue.offer(httpTask);
    }

    /**
     * 一直不停的去队列中拿到请求线程 然后交给线程池去执行
     */
    public Runnable runnable = new Runnable() {
        @Override
        public void run() {
            while (true){
                try {
                    //请求对象
                    Runnable runnable = mQueue.take();
                    threadPoolExecutor.execute(runnable);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    };


    /**
     * 专门处理失败请求的核心线程  它就是一直去失败队列中拿到请求然后重新执行
     */
    public Runnable faildRunable = new Runnable() {
        @Override
        public void run() {
            while (true){
                try {
                    HttpTask httpTask = (HttpTask) delayedsQueue.take();
                    //如果失败的次数不大于3次
                    if(httpTask.getMaxNum()<3){
                        httpTask.setMaxNum(httpTask.getMaxNum()+1);
                        threadPoolExecutor.execute(httpTask);
                        Log.e("请求重试机制-----------","我是次数"+httpTask.getMaxNum());
                    }else{
                        //如果大于3  就说明这个请求没有救了  就直接回调失败到应用层
                        httpTask.getiHttpRequest().getJasonCallbackListenner().onFaild();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    };
}
