package com.develop.food.base.timer

import java.util.*
import java.util.concurrent.*

/**
 * 长期执行的秒级任务
 */
class LongTermTaskTimer {
    private var mSECCountService: ScheduledExecutorService? = null
    private var mWorkPool: ThreadPoolExecutor? = null
    private var createTime = 0
    private var mWorkingMap: ConcurrentHashMap<String, Boolean> = ConcurrentHashMap()

    fun start() {
        if (mSECCountService == null) {
            mWorkingMap = ConcurrentHashMap(32)
            mWorkPool = ThreadPoolExecutor(4, 16, 120, TimeUnit.SECONDS, SynchronousQueue())
            mWorkPool?.threadFactory = ThreadFactory { r: Runnable? ->
                val thread = Thread(r)
                thread.name = String.format("bg-timer-%d", createTime++)
                thread
            }
            mWorkPool?.rejectedExecutionHandler =
                RejectedExecutionHandler { r: Runnable, executor: ThreadPoolExecutor? ->
                    val task = r as SECTask
                }
            val countTask = Runnable {
                for (task in mTasks.values) {
                    task.downCount()
                    if (task.canExecute()) {
                        if (mWorkingMap.containsKey(task.tag)) {
                        } else {
                            mWorkingMap[task.tag!!] = true
                            task.execute()
                        }
                    }
                }
            }
            mSECCountService = Executors.newSingleThreadScheduledExecutor()
            mSECCountService?.scheduleAtFixedRate(countTask, 1, 1, TimeUnit.SECONDS)
        }
    }

    fun stop() {
        if (mSECCountService != null) {
            mSECCountService?.shutdownNow()
            mWorkPool?.shutdownNow()
            mTasks.clear()
            mSECCountService = null
        }
    }

    private val mTasks: HashMap<String, SECTask> = HashMap()

    /**
     * 注册秒级执行任务
     *
     * @param tag
     * @param delaySecs
     * @param periodSecs
     * @param runnable
     */
    fun addSECLevelTask(tag: String?, delaySecs: Int, periodSecs: Int, runnable: Runnable?) {
        if (tag != null && !mTasks.containsKey(tag)) {
            val task = SECTask()
            task.tag = tag
            task.count = delaySecs
            task.period = periodSecs
            task.coreTask = runnable
            mTasks[tag] = task
        }
    }

    /**
     * 注册秒级执行任务
     *
     * @param tag
     */
    fun removeSECLevelTask(tag: String?) {
        if (tag != null) {
            mTasks.remove(tag)
        }
    }

    private inner class SECTask : Runnable {
        var tag: String? = null
        var period = 0
        var count = 0
        var coreTask: Runnable? = null
        fun downCount() {
            count--
        }

        fun canExecute(): Boolean {
            return count < 1
        }

        fun execute() {
            count = period
            mWorkPool?.execute(this)
        }

        override fun run() {
            try {
                coreTask?.run()
            } catch (e: Exception) {
                e.printStackTrace()
            }
            mWorkingMap.remove(tag!!)
        }

        override fun equals(other: Any?): Boolean {
            if (this === other) return true
            if (other == null || javaClass != other.javaClass) return false
            val secTask = other as SECTask
            return tag == secTask.tag
        }

        override fun hashCode(): Int {
            return Objects.hash(tag)
        }
    }

}