package com.gh.gamecenter.feature.view

import android.content.Context
import android.graphics.Color
import android.graphics.Typeface
import android.graphics.drawable.GradientDrawable
import android.text.TextUtils
import android.util.AttributeSet
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.TextView
import androidx.annotation.ColorRes
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager.widget.ViewPager
import androidx.viewpager2.widget.ViewPager2
import com.facebook.drawee.drawable.ScalingUtils
import com.facebook.drawee.generic.RoundingParams
import com.facebook.drawee.view.SimpleDraweeView
import com.gh.gamecenter.common.entity.IconFloat
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.common.view.RadiusCardView
import com.gh.gamecenter.core.utils.DisplayUtils
import com.gh.gamecenter.feature.R
import com.gh.gamecenter.feature.entity.GameEntity
import splitties.dimensions.dip
import splitties.views.dsl.core.*
import kotlin.math.abs

class GameIconView : FrameLayout {

    private var mCornerRadius = 0
    private var mBorderColor = 0
    private var mGameIconOverlayColor = 0
    private var mBorderWidth = 1
    private var mFadeDuration = -1

    private var mGameIconCv: RadiusCardView? = null
    private var mGameIconIv: SimpleDraweeView? = null
    private var mGameIconDecorationIv: SimpleDraweeView? = null
    private var mBorderView: View? = null
    private var mTopLabelContainer: FrameLayout? = null
    private var mTopLabelTv: TextView? = null
    private var mBottomLabelTv: TextView? = null
    private var mIsRemoveCrevice = false

    private var mIsTopLabelVisible = false
    private var mIsBottomLabelVisible = false

    constructor(context: Context) : super(context, null) {
        initView(null)
    }

    constructor(context: Context, attrs: AttributeSet) : super(context, attrs, 0) {
        initView(attrs)
    }

    constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    ) {
        initView(attrs)
    }

    fun initView(attrs: AttributeSet?) {
        val gameIconUi = GameIconUi(context)
        mGameIconCv = RadiusCardView(context)

        if (attrs != null && !isInEditMode) {
            val ta = context.obtainStyledAttributes(attrs, R.styleable.GameIconView)
            mCornerRadius = ta.getDimensionPixelSize(
                R.styleable.GameIconView_gameIconCornerRadius,
                DisplayUtils.dip2px(context, 0F)
            )
            mBorderColor = ta.getColor(R.styleable.GameIconView_gameIconBorderColor, 0)
            mGameIconOverlayColor = ta.getColor(R.styleable.GameIconView_gameIconOverlayColor, 0)
            mBorderWidth = ta.getDimensionPixelSize(R.styleable.GameIconView_gameIconBorderWidth, 1)
            mFadeDuration = ta.getInt(R.styleable.GameIconView_gameIconFadeDuration, -1)
            mIsRemoveCrevice = ta.getBoolean(R.styleable.GameIconView_gameIconRemoveCrevice, false)
            ta.recycle()
        }

        mGameIconCv?.add(gameIconUi.root, lParams(matchParent, matchParent) { })
        add(mGameIconCv!!, lParams(matchParent, matchParent) { })

        mGameIconIv = gameIconUi.gameIconIv
        mGameIconDecorationIv = gameIconUi.gameIconDecorationIv
        mBorderView = gameIconUi.borderView
        mBottomLabelTv = gameIconUi.bottomLabelTv

        mGameIconIv?.dimOnDarkMode()
        mGameIconDecorationIv?.dimOnDarkMode()

        mTopLabelTv = textView {
            setPadding(dip(6), dip(2), dip(6), 0)
            setTextColor(Color.WHITE)
            isSingleLine = true
            typeface = Typeface.DEFAULT_BOLD
            textSize = 10F
        }
        mTopLabelContainer = FrameLayout(context).apply {
            visibility = View.GONE
            add(mTopLabelTv!!, lParams(wrapContent, dip(24)) { })
        }

        val targetWidth = if (isInEditMode) 300 else DisplayUtils.getScreenWidth()
        add(mTopLabelContainer!!, lParams(targetWidth, wrapContent) { })

        if (mFadeDuration != -1) {
            mGameIconIv?.hierarchy?.fadeDuration = mFadeDuration
        }
        setBackgroundColor(Color.TRANSPARENT)
    }

    fun displayGameIcon(game: GameEntity) {
        if (!TextUtils.isEmpty(game.rawIcon)) {
            displayGameIcon(game.rawIcon ?: "", game.iconSubscript, game.iconFloat)
        } else {
            displayGameIcon(game.icon ?: "", null, game.iconFloat)
        }
    }

    fun displayGameIcon(game: GameEntity, hideBottomLabel: Boolean) {
        if (!TextUtils.isEmpty(game.rawIcon)) {
            displayGameIcon(game.rawIcon ?: "", game.iconSubscript, game.iconFloat, hideBottomLabel)
        } else {
            displayGameIcon(game.icon ?: "", null, game.iconFloat, hideBottomLabel)
        }
    }

    fun displayGameIconWithIfShowSubscript(game: GameEntity, showSubscript: Boolean) {
        if (showSubscript) {
            displayGameIcon(game)
        } else {
            if (!TextUtils.isEmpty(game.rawIcon)) {
                displayGameIcon(game.rawIcon ?: "", null, null)
            } else {
                displayGameIcon(game.icon ?: "", null, null)
            }
        }
    }

    fun displayGameIcon(icon: String?, iconSubscript: String?, iconFloat: IconFloat? = null) {
        displayGameIcon(icon, iconSubscript, false, iconFloat)
    }

    fun displayGameIcon(
        icon: String?,
        iconSubscript: String?,
        iconFloat: IconFloat? = null,
        hideBottomLabel: Boolean = false
    ) {
        displayGameIcon(icon, iconSubscript, false, iconFloat, hideBottomLabel)
    }

    fun displayGameIcon(
        icon: String?,
        iconSubscript: String?,
        goneIfEmpty: Boolean = false,
        iconFloat: IconFloat? = null,
        hideBottomLabel: Boolean = false
    ) {
        if (getTag(ImageUtils.TAG_TARGET_WIDTH) == null) {
            setTag(ImageUtils.TAG_TARGET_WIDTH, layoutParams.width)
        }

        setTag(ImageUtils.TAG_IS_GAME_ICON, true)

        mGameIconIv?.hierarchy?.setPlaceholderImage(
            ContextCompat.getDrawable(context, com.gh.gamecenter.common.R.drawable.occupy),
            ScalingUtils.ScaleType.FIT_XY
        )
        mGameIconIv?.aspectRatio = 1.0F

        mGameIconIv?.display(icon)
        mGameIconDecorationIv?.display(iconSubscript, true)
        if (iconFloat == null || (iconFloat.upperLeftText.isEmpty() && iconFloat.bottomText.isEmpty())) {
            mTopLabelContainer?.visibility = View.GONE
            mBottomLabelTv?.visibility = View.GONE
        } else {
            if (iconFloat.upperLeftText.isNotEmpty() && iconFloat.upperLeftColor.isNotEmpty()) {
                mIsTopLabelVisible = true
                mTopLabelContainer?.visibility = View.VISIBLE
                mTopLabelTv?.text = iconFloat.upperLeftText
                mTopLabelTv?.setBackgroundResource(if (iconFloat.upperLeftColor == "blue") com.gh.gamecenter.common.R.drawable.label_upperleft_blue else com.gh.gamecenter.common.R.drawable.label_upperleft_red)
                mTopLabelTv?.setPadding(dip(6), dip(2), dip(6), 0)
            } else {
                mIsTopLabelVisible = false
                mTopLabelContainer?.visibility = View.GONE
            }
            if (iconFloat.bottomText.isNotEmpty() && !hideBottomLabel) {
                mIsBottomLabelVisible = true
                mBottomLabelTv?.visibility = View.VISIBLE
                mBottomLabelTv?.text = iconFloat.bottomText
                mBottomLabelTv?.setBackgroundResource(com.gh.gamecenter.common.R.drawable.label_bottom)
            } else {
                mIsBottomLabelVisible = false
            }
        }
        if (goneIfEmpty) {
            visibility = if (TextUtils.isEmpty(icon)) View.GONE else View.VISIBLE
        }
    }

    fun getIconIv(): SimpleDraweeView = mGameIconIv!!

    fun getIconDecoratorIv(): SimpleDraweeView = mGameIconDecorationIv!!

    override fun setTag(key: Int, tag: Any?) {
        super.setTag(key, tag)
        mGameIconIv?.setTag(key, tag)
        mGameIconDecorationIv?.setTag(key, tag)
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        if (isInEditMode) {
            return
        }
        setBorder(w)
        setIconFloat(w)
    }

    private fun setIconFloat(width: Int) {
        val ratio = if (isInEditMode) 240F else width / SIZE_80.toFloat()
        val topLabelMarginLeft = dip(-2) * ratio
        val topLabelMarginTop = dip(-2) * ratio
        val bottomLabelPaddingBottom = (dip(3) * ratio).toInt()
        val offsetX = abs(topLabelMarginLeft)
        val offsetY = abs(topLabelMarginTop)

        mTopLabelTv?.run {
            pivotX = 0F
            pivotY = 0F
            scaleX = ratio
            scaleY = ratio
        }
        mTopLabelContainer?.run {
            layoutParams = (layoutParams as MarginLayoutParams).apply {
                setMargins(topLabelMarginLeft.toInt(), topLabelMarginTop.toInt(), 0, 0)
            }
        }
        mBottomLabelTv?.run {
            textSize = ratio * 10F
            setPadding(0, 0, 0, bottomLabelPaddingBottom)
        }
        setParentClip(this, offsetX, offsetY)
    }

    private fun setParentClip(view: View, offsetX: Float, offsetY: Float) {
        val viewParent = view.parent
        if (viewParent != null && viewParent is ViewGroup) {
            viewParent.clipChildren = false
            if (viewParent.paddingLeft != 0 || viewParent.paddingTop != 0) {
                viewParent.clipToPadding = false
            }
            if (view.x < offsetX || view.y < offsetY) {
                val parentOffsetX = if (view.x < offsetX) offsetX - view.x else 0F
                val parentOffsetY = if (view.y < offsetY) offsetY - view.y else 0F
                if (viewParent.parent is RecyclerView || viewParent.parent is ViewPager || viewParent.parent is ViewPager2) return
                setParentClip(viewParent, parentOffsetX, parentOffsetY)
            }
        }
    }

    private fun setBorder(width: Int) {
        val cornerRadius = if (!isInEditMode) {
            getCornerRadius(width)
        } else {
            0F
        }

        mGameIconCv?.setRadiusPx(cornerRadius, cornerRadius, cornerRadius, cornerRadius)
        mGameIconCv?.cardElevation = 0F

        // 一些设备(没错，又是 vivo)，代码设置 CardView 的 radius 无效(xml 设置有效)
        // 被迫再设置一次 SimpleDraweeView 的 radius :(
        val roundingParams = RoundingParams.fromCornersRadius(cornerRadius)
        if (mGameIconOverlayColor != 0) {
            roundingParams.overlayColor = mGameIconOverlayColor
        }

        if (mBorderColor != 0) {
            // 当图片为动图时，设置边框无效，所以改为增加一个View，专门用来设置边框
            //roundingParams.setBorder(mBorderColor, mBorderWidth.toFloat())
            val drawable = GradientDrawable().apply {
                shape = GradientDrawable.RECTANGLE
                //骚操作~ 这里加这个操作是为了防止图片和边框有间隙
                setCornerRadius(cornerRadius - if (mIsRemoveCrevice) mBorderWidth else 0)
                setColor(com.gh.gamecenter.common.R.color.transparent.toColor())
                setStroke(mBorderWidth, mBorderColor)
            }
            mBorderView?.background = drawable
        }

        //骚操作~ 这里加这个操作是为了防止图片和边框有间隙、防止右上角的静态小标签都被挡住
        if (mBorderWidth != 0) {
            val halfBorderWidth = (mBorderWidth / 2F).toInt()
            mGameIconIv?.setPadding(halfBorderWidth, halfBorderWidth, halfBorderWidth, halfBorderWidth)
            mGameIconDecorationIv?.setPadding(halfBorderWidth, halfBorderWidth, halfBorderWidth, halfBorderWidth)
        }

        mGameIconIv?.hierarchy?.roundingParams = roundingParams
        mGameIconDecorationIv?.hierarchy?.roundingParams = roundingParams
    }

    fun setCornerRadius(cornerRadius: Int) {
        mCornerRadius = cornerRadius
    }

    fun setBorderColor(@ColorRes color: Int) {
        mBorderColor = color.toColor(context)
        setBorder(measuredWidth)
    }

    private fun getCornerRadius(width: Int): Float {
        // 预设的圆角设置优先级更高
        if (mCornerRadius != 0) {
            return mCornerRadius.toFloat()
        }

        return when {
            width <= SIZE_36 -> RADIUS_8
            width >= SIZE_88 -> RADIUS_20
            width >= SIZE_80 -> RADIUS_18
            width >= SIZE_72 -> RADIUS_16
            width >= SIZE_64 -> RADIUS_14
            width >= SIZE_48 -> RADIUS_12
            width >= SIZE_40 -> RADIUS_10
            else -> RADIUS_8
        }
    }

    companion object {
        val RADIUS_8 by lazy { 8F.dip2px().toFloat() }
        val RADIUS_10 by lazy { 10F.dip2px().toFloat() }
        val RADIUS_12 by lazy { 12F.dip2px().toFloat() }
        val RADIUS_14 by lazy { 14F.dip2px().toFloat() }
        val RADIUS_16 by lazy { 16F.dip2px().toFloat() }
        val RADIUS_18 by lazy { 18F.dip2px().toFloat() }
        val RADIUS_20 by lazy { 20F.dip2px().toFloat() }

        val SIZE_36 by lazy { 36F.dip2px() }
        val SIZE_40 by lazy { 40F.dip2px() }
        val SIZE_48 by lazy { 48F.dip2px() }
        val SIZE_64 by lazy { 64F.dip2px() }
        val SIZE_72 by lazy { 72F.dip2px() }
        val SIZE_80 by lazy { 80F.dip2px() }
        val SIZE_88 by lazy { 88F.dip2px() }
    }

}
