package com.gh.gamecenter.feature.view

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.*
import android.text.TextPaint
import android.text.TextUtils
import android.util.AttributeSet
import android.view.MotionEvent
import android.widget.ProgressBar
import androidx.annotation.ColorInt
import androidx.annotation.StringRes
import com.gh.gamecenter.common.utils.toColor
import com.gh.gamecenter.common.utils.toDrawable
import com.gh.gamecenter.core.utils.DisplayUtils
import com.gh.gamecenter.feature.R
import com.gh.gamecenter.feature.provider.IDownloadButtonClickedProvider
import com.therouter.TheRouter

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

    private val mDuffXFerMode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)
    private val mPaint = Paint(Paint.ANTI_ALIAS_FLAG)

    // 仅用于测量文字是否超出范围，不用于画文字
    private val mFakeTextPaint = TextPaint(Paint.ANTI_ALIAS_FLAG)
    private var mDownloadStyle = 0
    private var mPaintColor = 0
    private var mDefaultColor = 0
    private var mPressedColor = 0
    private var mTextSize = DisplayUtils.sp2px(context, 12F)
    private var mText = ""
    private val mTextBound = Rect()

    private var srcBitmap: Bitmap? = null
    private var srcCanvas: Canvas? = null
    private var rectF: RectF? = null

    var buttonStyle = ButtonStyle.NORMAL
        set(value) {
            field = value
            updateStyle(value)
        }

    var text: String
        get() = mText
        set(value) {
            mText = value
            invalidate()
        }

    var showProgress = false
        set(value) {
            field = value
            updateStyle(buttonStyle)
        }

    private var mShowPercent = false

    init {
        if (attrs != null) {
            val ta = context.obtainStyledAttributes(attrs, com.gh.gamecenter.common.R.styleable.DownloadButton)
            showProgress =
                ta.getBoolean(com.gh.gamecenter.common.R.styleable.DownloadButton_download_button_show_progress, false)
            mShowPercent =
                ta.getBoolean(com.gh.gamecenter.common.R.styleable.DownloadButton_download_button_show_percent, false)
            mDownloadStyle =
                ta.getInteger(
                    com.gh.gamecenter.common.R.styleable.DownloadButton_download_button_download_style,
                    DOWNLOAD_NORMAL_STYLE
                )
            mTextSize = ta.getDimensionPixelSize(
                com.gh.gamecenter.common.R.styleable.DownloadButton_download_button_text_size,
                DisplayUtils.sp2px(context, 12F)
            )
            ta.recycle()
        }
        max = MAX_LENGTH
        updateStyle(buttonStyle)
    }

    private fun create() {
        if (measuredWidth > 0 && measuredHeight > 0) {
            srcBitmap = Bitmap.createBitmap(measuredWidth, measuredHeight, Bitmap.Config.ARGB_8888)
            srcCanvas = Canvas(srcBitmap!!)
            rectF = RectF(0F, 0F, (progress * width / max).toFloat(), measuredHeight.toFloat())
        }
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        if (mText.isEmpty()) return
        mPaint.color =
            if (mPaintColor == 0) com.gh.gamecenter.common.R.color.text_theme.toColor(context) else mPaintColor // 初始化颜色
        mPaint.textSize = mTextSize.toFloat()
        mFakeTextPaint.textSize = mTextSize.toFloat()
        mFakeTextPaint.style = Paint.Style.FILL_AND_STROKE
        mFakeTextPaint.textAlign = Paint.Align.CENTER
        mPaint.style = Paint.Style.FILL_AND_STROKE
        mPaint.xfermode = null
        create()

        val fontMetrics = mPaint.fontMetricsInt
        val baseline = (height - fontMetrics.bottom - fontMetrics.top) / 2

        mPaint.textAlign = Paint.Align.CENTER

        canvas.getClipBounds(mTextBound) //The dimensions of your canvas

        val width = mTextBound.width() - 20 //10 to keep some space on the right for the "..."
        val txt = TextUtils.ellipsize(mText, mFakeTextPaint, width.toFloat(), TextUtils.TruncateAt.END).toString()
        srcCanvas?.drawText(txt, getWidth() / 2F, baseline.toFloat(), mPaint)
        mPaint.xfermode = mDuffXFerMode
        if (progress != 0) {
            if (DOWNLOAD_IMAGE_STYLE == mDownloadStyle) {
                mPaint.color = Color.BLACK
            } else {
                mPaint.color = Color.WHITE
            }
        }

        rectF?.let { srcCanvas?.drawRect(it, mPaint) }
        srcBitmap?.let { canvas.drawBitmap(it, 0F, 0F, null) }
    }

    fun setText(@StringRes res: Int) {
        text = context.getString(res)
        invalidate()
    }

    fun setTextColor(@ColorInt defaultColor: Int, @ColorInt pressedColor: Int = 0) {
        mDefaultColor = defaultColor
        mPressedColor = pressedColor
        mPaintColor = mDefaultColor
        invalidate()
    }

    @Synchronized
    override fun setProgress(progress: Int) {
        super.setProgress(progress)
        if (showProgress && resources.getString(R.string.downloading) == mText) {
            text = "${progress / 10}%"
        }
    }

    private fun updateStyle(buttonStyle: ButtonStyle) {
        if (showProgress) {
            background = null
        } else {
            progressDrawable = null
            progress = 0
        }
        when (buttonStyle) {
            ButtonStyle.NORMAL,
            ButtonStyle.INSTALL_NORMAL,
            ButtonStyle.XAPK_FAILURE,
            ButtonStyle.NONE_WITH_HINT,
            ButtonStyle.H5_GAME,
            ButtonStyle.SPECIAL_DOWNLOAD,
            ButtonStyle.TEENAGER_MODE -> {
                progressDrawable = null
                background = when (mDownloadStyle) {
                    DOWNLOAD_IMAGE_STYLE -> R.drawable.text_white_background.toDrawable(context)
                    DOWNLOAD_HOME_PUSH_STYLE -> com.gh.gamecenter.common.R.drawable.bg_shape_theme_radius_999.toDrawable(
                        context
                    )

                    else -> com.gh.gamecenter.common.R.drawable.download_button_normal_style.toDrawable(context)
                }
                progress = 0
                mDefaultColor =
                    if (mDownloadStyle == DOWNLOAD_IMAGE_STYLE) com.gh.gamecenter.common.R.color.black.toColor(context) else com.gh.gamecenter.common.R.color.white.toColor(
                        context
                    )
            }

            ButtonStyle.LAUNCH_OR_OPEN -> {
                progressDrawable = null
                background = when (mDownloadStyle) {
                    DOWNLOAD_IMAGE_STYLE -> R.drawable.detail_download_open_image_style.toDrawable(context)
                    DOWNLOAD_HOME_PUSH_STYLE -> com.gh.gamecenter.common.R.drawable.bg_shape_theme_radius_999.toDrawable(
                        context
                    )

                    else -> com.gh.gamecenter.common.R.drawable.download_button_normal_style.toDrawable(context)
                }
                progress = 0
                mDefaultColor = com.gh.gamecenter.common.R.color.white.toColor(context)
            }

            ButtonStyle.RESERVABLE,
            ButtonStyle.UPDATING -> {
                progressDrawable = null
                background = R.drawable.download_button_updating_style.toDrawable(context)
                progress = 0
                mDefaultColor = com.gh.gamecenter.common.R.color.white.toColor(context)
            }

            ButtonStyle.FAILURE,
            ButtonStyle.NONE,
            ButtonStyle.RESERVED -> {
                progressDrawable = null
                background = R.drawable.button_round_gray_light.toDrawable(context)
                progress = 0
                mDefaultColor = com.gh.gamecenter.common.R.color.text_tertiary.toColor(context)
            }

            ButtonStyle.PLUGIN,
            ButtonStyle.INSTALL_PLUGIN -> {
                progressDrawable = null
                background = R.drawable.download_button_pluggable_style.toDrawable(context)
                progress = 0
                mDefaultColor = com.gh.gamecenter.common.R.color.white.toColor(context)
            }

            ButtonStyle.XAPK_SUCCESS,
            ButtonStyle.XAPK_UNZIPPING,
            ButtonStyle.DOWNLOADING_NORMAL -> {
                if (showProgress) {
                    progressDrawable =
                        if (mDownloadStyle == DOWNLOAD_IMAGE_STYLE) R.drawable.detail_downloading_normal_image_style.toDrawable(
                            context
                        ) else R.drawable.detail_downloading_normal_style.toDrawable(context)
                    mDefaultColor =
                        if (mDownloadStyle == DOWNLOAD_IMAGE_STYLE) com.gh.gamecenter.common.R.color.white.toColor(
                            context
                        ) else com.gh.gamecenter.common.R.color.text_theme.toColor(
                            context
                        )
                } else {
                    background = R.drawable.game_item_btn_downloading_style.toDrawable(context)
                    mDefaultColor = com.gh.gamecenter.common.R.color.text_theme.toColor(context)
                    mPressedColor = com.gh.gamecenter.common.R.color.white.toColor(context)
                }
            }

            ButtonStyle.DOWNLOADING_PLUGIN -> {
                if (showProgress) {
                    progressDrawable = R.drawable.detail_downloading_normal_style.toDrawable(context)
                    mDefaultColor = com.gh.gamecenter.common.R.color.text_theme.toColor(context)
                } else {
                    background = R.drawable.game_item_btn_downloading_style.toDrawable(context)
                    mDefaultColor = com.gh.gamecenter.common.R.color.text_theme.toColor(context)
                    mPressedColor = com.gh.gamecenter.common.R.color.white.toColor(context)
                }
            }

            ButtonStyle.WAITING -> {
                progressDrawable = null
                background = R.drawable.button_round_border_eeeeee.toDrawable(context)
                progress = 0
                mDefaultColor = com.gh.gamecenter.common.R.color.text_tertiary.toColor(context)
            }

            ButtonStyle.PAUSE -> {
                progressDrawable = null
                background = R.drawable.button_normal_round_border.toDrawable(context)
                progress = 0
                mDefaultColor = com.gh.gamecenter.common.R.color.text_theme.toColor(context)
            }

            ButtonStyle.ACCELERATING -> {
                progressDrawable = null
                background = com.gh.gamecenter.common.R.drawable.bg_common_button_light_fill_blue.toDrawable(context)
                progress = 0
                mDefaultColor = com.gh.gamecenter.common.R.color.primary_theme.toColor(context)
            }
        }
        mPaintColor = mDefaultColor
    }

    override fun setOnClickListener(listener: OnClickListener?) {
        // 供上一层处理点击事件，譬如点击日志记录等
        val clickHandler = TheRouter.get(IDownloadButtonClickedProvider::class.java)

        if (clickHandler != null && listener != null) {
            super.setOnClickListener { v ->
                clickHandler.onClicked(this)
                listener.onClick(v)
            }
        } else {
            super.setOnClickListener(listener)
        }
    }

    @SuppressLint("ClickableViewAccessibility")
    override fun onTouchEvent(event: MotionEvent?): Boolean {
        if ((event?.action == MotionEvent.ACTION_DOWN || event?.action == MotionEvent.ACTION_MOVE) && mPressedColor != 0) {
            mPaintColor = mPressedColor
        } else if (event?.action == MotionEvent.ACTION_CANCEL && mPaintColor != mDefaultColor) {
            mPaintColor = mDefaultColor
        } else if (event?.action == MotionEvent.ACTION_UP && mPaintColor != mDefaultColor) {
            postDelayed({
                mPaintColor = mDefaultColor
            }, 50)
        }
        return super.onTouchEvent(event)
    }

    enum class ButtonStyle {
        NORMAL,
        NONE,
        NONE_WITH_HINT,
        PLUGIN,
        LAUNCH_OR_OPEN,
        INSTALL_NORMAL,
        INSTALL_PLUGIN,
        DOWNLOADING_NORMAL,
        DOWNLOADING_PLUGIN,
        RESERVABLE,
        RESERVED,
        H5_GAME,
        UPDATING,
        TEENAGER_MODE,
        SPECIAL_DOWNLOAD,
        WAITING,
        PAUSE,
        FAILURE,
        XAPK_UNZIPPING,
        XAPK_SUCCESS,
        XAPK_FAILURE,
        ACCELERATING
    }

    companion object {
        const val MAX_LENGTH = 1000
        const val DOWNLOAD_NORMAL_STYLE = 0
        const val DOWNLOAD_HOME_PUSH_STYLE = 1
        const val DOWNLOAD_IMAGE_STYLE = 2
    }

    interface OnUpdateListener {

        fun completion(text: String)
    }
}