package com.gh.gamecenter.common.utils

import androidx.core.util.Pools
import com.facebook.drawee.controller.BaseControllerListener
import com.facebook.drawee.view.SimpleDraweeView
import com.facebook.imagepipeline.image.ImageInfo
import com.facebook.imagepipeline.request.Postprocessor
import com.gh.gamecenter.core.utils.SingletonHolder

class AsyncImageLoader private constructor() {

    fun addAsyncImage(view: SimpleDraweeView?, url: String, loadAsAnimatedImage: Boolean, processor: Postprocessor?, controllerListener: BaseControllerListener<ImageInfo>?) {
        try {
            val loopThread = LoopThread.getInstance()
            val params = loopThread.obtainImageParams()
            params.view = view
            params.url = url
            params.loadAsAnimatedImage = loadAsAnimatedImage
            params.processor = processor
            params.controllerListener = controllerListener
            loopThread.addAsyncImage(params)
        } catch (e: InterruptedException) {
            e.printStackTrace()
        }
    }

    private class LoopThread private constructor() : Thread("GH_LOOP_IMAGE_LOADER") {

        private var mIsLoop = false
        private val mRetryCount = 3
        private val mInterval = 10L
        private val mImageList = ArrayList<ImageLoadParams>()
        private val mImageListTemp = ArrayList<ImageLoadParams>()
        private val mImagePool = Pools.SynchronizedPool<ImageLoadParams>(15)

        init {
            start()
        }

        @Synchronized
        fun addAsyncImage(image: ImageLoadParams) {
            if (mIsLoop) {
                mImageListTemp.add(image)
            } else {
                mImageList.add(image)
            }
        }

        override fun run() {
            rxTimerWithIoThread(mInterval) {
                try {
                    if (!mIsLoop) {
                        runInner()
                    }
                } catch (e: Exception) {
                    e.printStackTrace()
                }
            }
        }

        private fun runInner() {
            if (mImageList.isEmpty()) return

            mIsLoop = true
            mImageList.forEach { image ->
                val width = image.view?.width ?: 0
                if (width == 0) {
                    if (image.retryCount >= mRetryCount) {
                        loadImage(image, true)
                    } else {
                        image.retryCount += 1
                        mImageListTemp.add(image)
                    }
                } else {
                    if (image.view?.getTag(ImageUtils.TAG_TARGET_WIDTH) == null) {
                        image.view?.setTag(ImageUtils.TAG_TARGET_WIDTH, width)
                    }
                    loadImage(image)
                }
            }
            mImageList.clear()

            if (mImageListTemp.isNotEmpty()) {
                mImageList.addAll(mImageListTemp)
                mImageListTemp.clear()
            }
            mIsLoop = false
        }


        private fun loadImage(params: ImageLoadParams, isIgnoreWidth: Boolean = false) {
            ImageUtils.display(params.view, params.url, params.loadAsAnimatedImage, params.processor, isIgnoreWidth, params.controllerListener)
            releaseImageParams(params)
        }

        fun obtainImageParams(): ImageLoadParams {
            var acquire = mImagePool.acquire()
            if (acquire == null) {
                acquire = ImageLoadParams()
            }
            return acquire
        }

        private fun releaseImageParams(params: ImageLoadParams) {
            params.run {
                view = null
                url = ""
                loadAsAnimatedImage = false
                processor = null
                retryCount = 0
                controllerListener = null
                mImagePool.release(this)
            }
        }

        companion object : SingletonHolder<LoopThread>({ LoopThread() })
    }

    companion object : SingletonHolder<AsyncImageLoader>({ AsyncImageLoader() })
}

class ImageLoadParams(
    var view: SimpleDraweeView? = null,
    var url: String = "",
    var loadAsAnimatedImage: Boolean = true,
    var processor: Postprocessor? = null,
    var retryCount: Int = 0,
    var controllerListener: BaseControllerListener<ImageInfo>? = null,
)