package com.gh.gamecenter.common.view

import android.content.Context
import android.graphics.drawable.Animatable
import android.util.AttributeSet
import androidx.annotation.Nullable
import androidx.core.view.updateLayoutParams
import com.facebook.drawee.backends.pipeline.PipelineDraweeController
import com.facebook.drawee.controller.BaseControllerListener
import com.facebook.drawee.interfaces.DraweeController
import com.facebook.drawee.view.SimpleDraweeView
import com.facebook.imagepipeline.image.ImageInfo
import com.gh.gamecenter.common.utils.dip2px

class WrapContentDraweeView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : SimpleDraweeView(context, attrs, defStyleAttr) {

    private var mLoadingCallback: LoadingCallback? = null

    // 可显示的最大和最小尺寸（用于正方形空间限制）
    private var mMaxSize = -1
    private var mMinSize = -1
    // 切换成可显示的最大和最小尺寸前是否需要除以固定的值
    private var mSubsampleSize = 1
    // 可显示的最大高度，仅限制高度
    private var mFixedHeight = -1

    // we set a listener and update the view's aspect ratio depending on the loaded image
    private val mListener = object : BaseControllerListener<ImageInfo>() {
        override fun onIntermediateImageSet(id: String?, imageInfo: ImageInfo?) {
            if (mMaxSize != -1) {
                resizeToFitMaximumOrMinimumSize(imageInfo)
            } else if (mFixedHeight != -1) {
                resizeToFixedHeight(imageInfo)
            }

            updateViewSize(imageInfo)

            mLoadingCallback?.loaded()
        }

        override fun onFinalImageSet(id: String?, imageInfo: ImageInfo?, animatable: Animatable?) {
            if (mMaxSize != -1) {
                resizeToFitMaximumOrMinimumSize(imageInfo)
            } else if (mFixedHeight != -1) {
                resizeToFixedHeight(imageInfo)
            }

            updateViewSize(imageInfo)

            mLoadingCallback?.loaded()
        }

        override fun onFailure(id: String?, throwable: Throwable?) {
            mLoadingCallback?.loaded()
        }
    }

    // TODO 自动图片加载监听
    fun registerLoadingCallback(loadingCallback: LoadingCallback) {
        mLoadingCallback = loadingCallback
    }

    /**
     * 设置最大和最小尺寸
     * 单位为 dp
     */
    fun setMaxAndMinSizeLimit(maxSize: Int, minSize: Int) {
        mMaxSize = maxSize
        mMinSize = minSize
    }

    /**
     * 取样的倍率（如传入值为 4 即表示取原图的 1/4 作为小样）
     */
    fun setSubsampleSize(subsampleSize: Int) {
        mSubsampleSize = subsampleSize
    }

    /**
     * 设置最大高度 (与设置最大和最小尺寸互斥)
     * 单位为 dp
     */
    fun setFixedHeight(fixedHeight: Int) {
        mFixedHeight = fixedHeight
    }

    /**
     * 根据设置的最大和最小尺寸来改变的显示大小
     *
     * 大于最大尺寸，以最大尺寸作为长边等比例缩小
     *
     * 小于最小尺寸，以最小尺寸作为长边等比例拉伸
     */
    private fun resizeToFitMaximumOrMinimumSize(imageInfo: ImageInfo?) {
        imageInfo ?: return

        val originalImageHeight = imageInfo.height / mSubsampleSize
        val originalImageWidth = imageInfo.width / mSubsampleSize

        var resizedImageHeight = originalImageHeight
        var resizedImageWidth = originalImageHeight

        val ratio = originalImageWidth.toFloat() / originalImageHeight

        if (originalImageHeight > mMaxSize || originalImageWidth > mMaxSize) {
            // 缩小最长边，短边等比例缩放
            if (originalImageHeight > originalImageWidth) {
                resizedImageHeight = mMaxSize
                resizedImageWidth = (resizedImageHeight * ratio).toInt()
            } else {
                resizedImageWidth = mMaxSize
                resizedImageHeight = (resizedImageWidth / ratio).toInt()
            }
        } else if (originalImageHeight < mMinSize && originalImageWidth < mMinSize) {
            // 拉伸最长边，短边等比例缩放
            if (originalImageHeight > originalImageWidth) {
                resizedImageHeight = mMinSize
                resizedImageWidth = (resizedImageHeight * ratio).toInt()
            } else {
                resizedImageWidth = mMinSize
                resizedImageHeight = (resizedImageWidth / ratio).toInt()
            }
        }

        updateLayoutParams {
            height = resizedImageHeight.toFloat().dip2px()
            width = resizedImageWidth.toFloat().dip2px()
        }
    }

    private fun resizeToFixedHeight(imageInfo: ImageInfo?) {
        imageInfo ?: return

        val originalImageHeight = imageInfo.height / mSubsampleSize
        val originalImageWidth = imageInfo.width / mSubsampleSize

        val ratio = originalImageWidth.toFloat() / originalImageHeight

        val resizedImageHeight: Int = mFixedHeight
        val resizedImageWidth = (resizedImageHeight * ratio).toInt()

        updateLayoutParams {
            height = resizedImageHeight.toFloat().dip2px() + paddingTop + paddingBottom
            width = resizedImageWidth.toFloat().dip2px() + paddingLeft + paddingRight
        }
    }

    override fun setController(draweeController: DraweeController?) {
        if (draweeController is PipelineDraweeController) {
            draweeController.addControllerListener(mListener)
        }
        super.setController(draweeController)
    }

    internal fun updateViewSize(@Nullable imageInfo: ImageInfo?) {
        if (imageInfo != null) {
            aspectRatio = imageInfo.width.toFloat() / imageInfo.height
        }
    }

    interface LoadingCallback {
        fun loaded()
    }
}