package com.gh.common.prioritychain

import com.lightgame.utils.Utils
import java.util.*

abstract class PriorityChainHandler(private val mPriority: Int) : Comparable<PriorityChainHandler> {

    private var status = STATUS_UNKNOWN
    private var queue: Queue<PriorityChainHandler>? = null

    private var priorityChain: PriorityChain? = null

    /**
     * 获取当前 handler 的状态
     * - 等待结果返回 （STATUS_PENDING）
     * - 无需执行 （STATUS_INVALID）
     * - 可执行 （STATUS_VALID）
     * - 执行中 （STATUS_HANDLING）
     * - 未知 （STATUS_UNKNOWN）
     */
    fun getStatus(): Int = status

    fun updateStatus(status: Int) {
        Utils.log(TAG, "${javaClass.simpleName} updateStatus ${this.status} $status")

        this.status = status
    }

    fun setPriorityChain(priorityChain: PriorityChain) {
        this.priorityChain = priorityChain
    }

    fun injectQueue(queue: Queue<PriorityChainHandler>) {
        this.queue = queue
    }

    fun process() {
        Utils.log(TAG, "${javaClass.simpleName} process $status")

        // 若当前 handler 未经处理，将其状态改为 pending
        if (status == STATUS_UNKNOWN) {
            updateStatus(STATUS_PENDING)
        }

        if (status == STATUS_HANDLING) {
            Utils.log(TAG, "${javaClass.simpleName} 已经处于执行中状态，不用再次执行")
            return
        }

        val isHandling = onProcess()

        if (isHandling) {
            updateStatus(STATUS_HANDLING)
        }
    }

    /**
     * 执行相关功能的地方
     * @return 是否满足执行条件并处于执行中状态
     */
    abstract fun onProcess(): Boolean

    /**
     * 分发给下一个 handler 处理
     */
    fun processNext() {
        Utils.log(TAG, "${javaClass.simpleName} processNext")

        queue?.remove(this)
        if (queue?.isEmpty() == true) {
            priorityChain?.onHandleComplete()
        } else {
            queue?.peek()?.let {
                it.injectQueue(queue!!)
                it.process()
            }
        }
    }

    override fun compareTo(other: PriorityChainHandler): Int {
        return (mPriority - other.mPriority)
    }

    companion object {
        internal const val STATUS_PENDING = 0
        internal const val STATUS_INVALID = 1
        internal const val STATUS_VALID = 2
        internal const val STATUS_UNKNOWN = 3
        internal const val STATUS_HANDLING = 4

        const val TAG = "PriorityChainHandler"
    }

}