package com.gh.common.util

import android.content.Context
import android.graphics.Color
import android.text.Spannable
import android.text.SpannableStringBuilder
import android.text.Spanned
import android.text.TextPaint
import android.text.method.LinkMovementMethod
import android.text.style.ClickableSpan
import android.text.style.ForegroundColorSpan
import android.text.style.UnderlineSpan
import android.view.View
import android.widget.TextView
import androidx.annotation.StringRes
import androidx.core.content.ContextCompat

/**
 * @author : liujiarui
 * date : 2023/3/22
 * description : 文本颜色事件控制
 */
//作用域进行限制
@DslMarker
@Target(AnnotationTarget.TYPE)
annotation class TextSpanDsl

interface DslSpannableStringBuilder {
    //增加一段文字
    fun addText(text: String, method: (@TextSpanDsl DslSpanBuilder.() -> Unit)? = null)
    fun addText(@StringRes stringRes: Int, method: (@TextSpanDsl DslSpanBuilder.() -> Unit)? = null)
}

interface DslSpanBuilder {
    //设置文字颜色文本
    fun setColor(color: String)

    //设置文字颜色int
    fun setColor(color: ColorInt)

    //设置文字颜色id
    fun setColor(color: ColorResId)

    //设置点击事件
    fun onClick(useUnderLine: Boolean = false, onClick: (View) -> Unit)
}

//为 TextView 创建扩展函数，其参数为接口的扩展函数
fun TextView.buildSpannableString(init: @TextSpanDsl DslSpannableStringBuilder.() -> Unit) {
    //具体实现类
    val spanStringBuilderImpl = DslSpannableStringBuilderImpl(context)
    spanStringBuilderImpl.init()
    movementMethod = LinkMovementMethod.getInstance()
    //通过实现类返回SpannableStringBuilder
    text = spanStringBuilderImpl.build()
}

class DslSpannableStringBuilderImpl(val context: Context) : DslSpannableStringBuilder {
    private val builder = SpannableStringBuilder()

    //记录上次添加文字后最后的索引值
    private var lastIndex: Int = 0
    var isClickable = false

    override fun addText(text: String, method: (@TextSpanDsl DslSpanBuilder.() -> Unit)?) {
        val start = lastIndex
        builder.append(text)
        lastIndex += text.length
        val spanBuilder = DslSpanBuilderImpl(context)
        method?.let { spanBuilder.it() }
        spanBuilder.apply {
            onClickSpan?.let {
                builder.setSpan(it, start, lastIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
                isClickable = true
            }
            if (!useUnderLine) {
                val noUnderlineSpan = NoUnderlineSpan()
                builder.setSpan(noUnderlineSpan, start, lastIndex, Spanned.SPAN_MARK_MARK)
            }
            foregroundColorSpan?.let {
                builder.setSpan(it, start, lastIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
            }
        }
    }

    override fun addText(stringRes: Int, method: (@TextSpanDsl DslSpanBuilder.() -> Unit)?) {
        val text = context.getString(stringRes)
        addText(text, method)
    }

    fun build(): SpannableStringBuilder {
        return builder
    }
}

class DslSpanBuilderImpl(val context: Context) : DslSpanBuilder {
    var foregroundColorSpan: ForegroundColorSpan? = null
    var onClickSpan: ClickableSpan? = null
    var useUnderLine = true

    override fun setColor(color: String) {
        foregroundColorSpan = ForegroundColorSpan(Color.parseColor(color))
    }

    override fun setColor(color: ColorInt) {
        foregroundColorSpan = ForegroundColorSpan(color.color)
    }

    override fun setColor(color: ColorResId) {
        val c = ContextCompat.getColor(context, color.colorResId)
        foregroundColorSpan = ForegroundColorSpan(c)
    }

    override fun onClick(useUnderLine: Boolean, onClick: (View) -> Unit) {
        onClickSpan = object : ClickableSpan() {
            override fun onClick(widget: View) {
                onClick(widget)
            }
        }
        this.useUnderLine = useUnderLine
    }
}

@JvmInline
value class ColorInt(val color: Int)

@JvmInline
value class ColorResId(val colorResId: Int)

class NoUnderlineSpan : UnderlineSpan() {
    override fun updateDrawState(ds: TextPaint) {
        ds.color = ds.linkColor
        ds.isUnderlineText = false
    }
}