package com.gh.gamecenter.game.vertical

import android.content.Context
import android.graphics.Color
import android.graphics.Typeface
import android.text.TextUtils
import android.util.AttributeSet
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.widget.LinearLayout
import android.widget.Space
import android.widget.TextView
import androidx.appcompat.content.res.AppCompatResources
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat
import com.airbnb.lottie.LottieAnimationView
import com.airbnb.lottie.LottieDrawable
import com.facebook.drawee.view.SimpleDraweeView
import com.gh.gamecenter.R
import com.gh.gamecenter.common.databinding.LayoutGameItemSellingPointBinding
import com.gh.gamecenter.common.utils.setDrawableEnd
import com.gh.gamecenter.common.view.GameTagContainerView
import com.gh.gamecenter.feature.view.DownloadButton
import com.gh.gamecenter.feature.view.GameIconView
import splitties.dimensions.dip
import splitties.views.backgroundColor
import splitties.views.dsl.constraintlayout.*
import splitties.views.dsl.core.*
import splitties.views.dsl.idepreview.UiPreView
import splitties.views.endPadding
import splitties.views.padding
import splitties.views.startPadding

/**
 * 代码生成版的 game_item.xml 布局（有删减，部分非通用的 view 并没有包括在内），规避 view 从 xml inflate 成对象的时间
 *
 * 预览方式
 * 修改后 make project 然后点击右上角的 Split
 *
 * 注意事项
 *
 * 1. 需要处理完报错以后再 make project 不然下一次 make project 需要全局重新编译（我也不知道为啥）
 * 2. 不要用一些全局静态方法来显示页面，因为预览时相应的静态内容没有被初始化（如 HaloApp）
 * 3. 注意 padding 和 margin 的作用域
 */
class GameItemUi(override val ctx: Context) : Ui {

    var iconIv: GameIconView
    var gameNameContainer: LinearLayout
    var gameNameTv: TextView
    var gameSubtitleTv: TextView
    var adLabelTv: TextView
    var downloadTv: DownloadButton
    var multiVersionDownloadTv: TextView
    var downloadTipsLottie: LottieAnimationView
    var gameDesTv: TextView
    var serverTypeTv: TextView
    var gameRatingTv: TextView
    var recommendIv: SimpleDraweeView
    var recommendTv: TextView
    var gameTagContainer: GameTagContainerView
    var recommendConstraintLayout: ConstraintLayout
    var gamePlayCountTv: TextView

    var mGameDesSpace: Space
    var sellingPointsBinding: LayoutGameItemSellingPointBinding

    override val root: ConstraintLayout = constraintLayout {
        padding = dip(16)

        iconIv = initIconView()
        serverTypeTv = initServerTypeTv()
        gameNameTv = initGameNameTv()
        gameSubtitleTv = initGameSubtitleTv()
        adLabelTv = initAdLabelTv()
        gameNameContainer = initGameNameContainer()
        downloadTv = initDownloadTv()
        multiVersionDownloadTv = initMultiVersionDownloadTv()
        downloadTipsLottie = initDownloadTipsLottie()
        gameDesTv = initGameDesTv()
        gameRatingTv = initGameRatingTv()
        recommendIv = SimpleDraweeView(ctx).apply { id = R.id.recommendIv }
        recommendTv = initRecommendTv()
        gamePlayCountTv = initGamePlayCountTv()
        gameTagContainer = GameTagContainerView(ctx).apply { id = R.id.label_list }
        mGameDesSpace = space { }.apply { id = R.id.gameDesSpace }
        recommendConstraintLayout = initRecommendConstraintLayout()
        sellingPointsBinding = LayoutGameItemSellingPointBinding.inflate(LayoutInflater.from(context))

        add(iconIv, lParams(dip(64), dip(64)) {
            topOfParent()
            bottomOfParent()
            startOfParent()
        })
        add(downloadTv, lParams(dip(56), dip(28)) {
            topOfParent()
            endOfParent()
            bottomOfParent()
        })
        add(multiVersionDownloadTv, lParams(wrapContent, dip(28)) {
            topToTopOf(downloadTv)
            bottomToBottomOf(downloadTv)
            startToStartOf(downloadTv)
            endToEndOf(downloadTv)
        })
        add(downloadTipsLottie, lParams(dip(16), dip(16)) {
            topToTopOf(downloadTv)
            endToEndOf(downloadTv)

            topMargin = dip(-8)
        })
        add(mGameDesSpace, lParams(0, dip(28)) {
            startToEndOf(iconIv, dip(12))
            endToStartOf(downloadTv, dip(8))
            topToBottomOf(gameNameContainer)
            bottomToTopOf(gameTagContainer)
        })
        add(gameRatingTv, lParams(wrapContent, wrapContent) {
            horizontalChainStyle = packed
            startToStartOf(mGameDesSpace)
            endToStartOf(gameDesTv)
            topToTopOf(mGameDesSpace)
            bottomToBottomOf(mGameDesSpace)
        })
        add(gameDesTv, lParams(0, wrapContent) {
            startToEndOf(gameRatingTv)
            endToEndOf(mGameDesSpace)
            topToTopOf(mGameDesSpace)
            bottomToBottomOf(mGameDesSpace)
        })
        add(recommendConstraintLayout, lParams(wrapContent, dip(18)) {
            startToStartOf(mGameDesSpace)
            endToEndOf(mGameDesSpace)
            topToTopOf(mGameDesSpace)

            topMargin = dip(3)
            constrainedWidth = true
            horizontalBias = 0F
        })
        add(gameTagContainer, lParams(0, wrapContent) {
            topToBottomOf(mGameDesSpace)
            bottomToBottomOf(iconIv)
            startToEndOf(gamePlayCountTv)
            endToEndOf(mGameDesSpace)
            orientation = LinearLayout.HORIZONTAL
        })
        add(sellingPointsBinding.root, lParams(0, wrapContent) {
            topToBottomOf(mGameDesSpace)
            bottomToBottomOf(iconIv)
            startToEndOf(gamePlayCountTv)
            endToEndOf(mGameDesSpace)
        })
        add(gamePlayCountTv, lParams(wrapContent, wrapContent) {
            topToBottomOf(mGameDesSpace)
            bottomToBottomOf(iconIv)
            startToStartOf(mGameDesSpace)
            endToStartOf(gameTagContainer)
            endMargin = dip(8)
        })
        add(gameNameContainer, lParams(0, wrapContent) {
            startToStartOf(mGameDesSpace)
            topToTopOf(iconIv)
            endToEndOf(mGameDesSpace)
            bottomToTopOf(mGameDesSpace)

            orientation = LinearLayout.HORIZONTAL
            verticalChainStyle = packed
        })
    }

    private fun initIconView(): GameIconView {
        return GameIconView(ctx).apply {
            id = R.id.gameIconView
        }
    }

    private fun initGameNameContainer() = LinearLayout(ctx).apply {
        gravity = Gravity.CENTER_VERTICAL
        add(gameNameTv, lParams(wrapContent, wrapContent) {})
        add(gameSubtitleTv, lParams(wrapContent, dip(14)) {
            startMargin = dip(4)
        })
        add(serverTypeTv, lParams(wrapContent, wrapContent) {
            startMargin = dip(4)
        })
        add(adLabelTv, lParams(dip(21), dip(14)) {
            startMargin = dip(4)
        })
    }

    private fun initGameNameTv() = textView {
        id = R.id.game_name
        setSingleLine()
        includeFontPadding = false
        typeface = Typeface.DEFAULT_BOLD
        textSize = 14F
        ellipsize = TextUtils.TruncateAt.END
        setTextColor(ContextCompat.getColor(context, com.gh.gamecenter.common.R.color.text_primary))
    }

    private fun initGameSubtitleTv() = textView {
        id = R.id.gameSubtitleTv
        setSingleLine()
        textSize = 10F
        startPadding = dip(2)
        endPadding = dip(2)
        ellipsize = TextUtils.TruncateAt.END
        background =
            ContextCompat.getDrawable(context, com.gh.gamecenter.feature.R.drawable.bg_advance_download_game_subtitle)
        setTextColor(ContextCompat.getColor(context, com.gh.gamecenter.common.R.color.text_secondary))
        visibility = View.GONE
    }

    private fun initAdLabelTv() = textView {
        id = R.id.adLabelTv
        textSize = 10F
        text = "AD"
        gravity = Gravity.CENTER
        background = ContextCompat.getDrawable(context, R.drawable.bg_ad_label)
        setTextColor(Color.WHITE)
        visibility = View.GONE
    }

    private fun initServerTypeTv() = textView {
        id = R.id.game_server_type
        height = dip(14)
        textSize = 10F
        setTextColor(Color.WHITE)
        gravity = Gravity.CENTER
        maxLines = 1
        backgroundColor = ContextCompat.getColor(context, com.gh.gamecenter.common.R.color.primary_theme)

        visibility = View.GONE

        startPadding = dip(4)
        endPadding = dip(4)
    }

    private fun initGameDesTv() = textView {
        id = R.id.game_des
        textSize = 10F
        setSingleLine()
        includeFontPadding = false
        ellipsize = TextUtils.TruncateAt.END
        setTextColor(ContextCompat.getColor(context, com.gh.gamecenter.common.R.color.text_tertiary))
    }

    private fun initGamePlayCountTv() = textView {
        id = R.id.game_play_count
        textSize = 11F
        includeFontPadding = false
        gravity = Gravity.CENTER
        setTextColor(ContextCompat.getColor(context, com.gh.gamecenter.common.R.color.text_tertiary))
        visibility = View.GONE
    }

    private fun initDownloadTv() = DownloadButton(ctx).apply {
        id = R.id.download_btn
        text = "下载"
        showProgress = true
    }

    private fun initGameRatingTv() = textView {
        id = R.id.game_rating
        typeface = Typeface.DEFAULT_BOLD
        compoundDrawablePadding = dip(4)
        includeFontPadding = false

        visibility = View.VISIBLE
    }

    private fun initRecommendConstraintLayout() = constraintLayout {
        id = R.id.recommendContainer
        startPadding = dip(4)
        endPadding = dip(8)
        visibility = View.GONE
        background = ContextCompat.getDrawable(context, com.gh.gamecenter.feature.R.drawable.bg_game_item_recommend)

        add(recommendIv, lParams(dip(12), dip(12)) {
            topOfParent()
            bottomOfParent()
            startOfParent()
        })
        add(recommendTv, lParams(0, wrapContent) {
            bottomOfParent()
            endOfParent()
            topOfParent()
            startToEndOf(recommendIv)

            horizontalBias = 0F
            matchConstraintDefaultWidth = 1

            startMargin = dip(2)
            goneStartMargin = dip(4)
        })
    }

    private fun initRecommendTv() = textView {
        id = R.id.recommendTv
        textSize = 10F
        maxLines = 1
        includeFontPadding = false
        typeface = Typeface.DEFAULT_BOLD
        gravity = Gravity.START.and(Gravity.CENTER)
        ellipsize = TextUtils.TruncateAt.END

        setTextColor(ContextCompat.getColor(context, com.gh.gamecenter.common.R.color.text_FF7C1F))
    }

    private fun initMultiVersionDownloadTv(): TextView {
        return textView {
            id = R.id.multiVersionDownloadTv
            textSize = 12F
            gravity = Gravity.CENTER
            text = "展开"
            setTextColor(ContextCompat.getColor(context, com.gh.gamecenter.common.R.color.white))
            setDrawableEnd(
                AppCompatResources.getDrawable(
                    context,
                    com.gh.gamecenter.feature.R.drawable.ic_jump_universal
                )
            )
            compoundDrawablePadding = dip(2)
            visibility = View.GONE
        }
    }

    private fun initDownloadTipsLottie(): LottieAnimationView {
        return LottieAnimationView(ctx).apply {
            id = R.id.downloadTipsLottie
            repeatMode = LottieDrawable.RESTART
            repeatCount = LottieDrawable.INFINITE
            visibility = View.GONE
        }
    }

}

@Deprecated("For IDE preview only", level = DeprecationLevel.HIDDEN)
private class GameItemUiPreview(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : UiPreView(
    context = context.withTheme(R.style.AppCompatTheme_APP),
    attrs = attrs,
    defStyleAttr = defStyleAttr,
    createUi = {
        GameItemUi(it).apply {
//            recommendConstraintLayout.visibility = View.VISIBLE
            iconIv.setCornerRadius(0)

            gameNameTv.text = "地海争霸：巫妖王再怒"
            gameDesTv.text = "巫妖王再怒霜之哀殤又飢渴"

            serverTypeTv.visibility = View.VISIBLE
            serverTypeTv.backgroundColor = Color.RED
            serverTypeTv.text = "地球服"
        }
    }
)