package com.remax.visualnovel.widget.ui


import android.content.Context
import android.graphics.*
import android.graphics.drawable.Drawable
import android.text.TextPaint
import androidx.annotation.StringRes
import androidx.core.content.ContextCompat
import com.remax.visualnovel.extension.getIconFontType
import com.remax.visualnovel.utils.spannablex.utils.dp


/**
 * Embed an icon into a Drawable that can be used as TextView icons, or ActionBar icons.
 * <pre>
 * new IconDrawable(context, IconValue.icon_star)
 * .colorRes(R.color.white)
 * .actionBarSize();
</pre> *
 * If you don't set the size of the drawable, it will use the size
 * that is given to him. Note that in an ActionBar, if you don't
 * set the size explicitly it uses 0, so please use actionBarSize().
 */
class IconFontDrawable : Drawable {
    private var context: Context? = null
    private var icon: String? = null
    private var paint: TextPaint? = null
    private var size = -1
    private var alphaValue = 255

    /**
     * Create an IconDrawable.
     *
     * @param context Your activity or application context.
     * @param icon    The icon key you want this drawable to display.
     */
    constructor(context: Context, icon: String) {
        init(context, icon)
    }

    constructor(context: Context, @StringRes iconKey: Int) {
        init(context, context.getString(iconKey))
    }

    private fun init(context: Context, icon: String) {
        this.context = context
        this.icon = icon
        paint = TextPaint().apply {
            typeface = context.getIconFontType()
            style = Paint.Style.FILL
            textAlign = Paint.Align.CENTER
            isUnderlineText = false
            color = Color.BLACK
            isAntiAlias = true
        }
    }

    /**
     * Set the size of the drawable.
     *
     * @param dimenRes The dimension resource.
     * @return The current IconDrawable for chaining.
     */
    fun sizeRes(dimenRes: Int): IconFontDrawable {
        return sizePx(context!!.resources.getDimensionPixelSize(dimenRes))
    }

    /**
     * Set the size of the drawable.
     *
     * @param size The size in density-independent pixels (dp).
     * @return The current IconDrawable for chaining.
     */
    fun sizeDp(size: Int): IconFontDrawable {
        return sizePx(size.dp)
    }

    /**
     * Set the size of the drawable.
     *
     * @param size The size in pixels (px).
     * @return The current IconDrawable for chaining.
     */
    fun sizePx(size: Int): IconFontDrawable {
        this.size = size
        setBounds(0, 0, size, size)
        invalidateSelf()
        return this
    }

    /**
     * Set the color of the drawable.
     *
     * @param color The color, usually from android.graphics.Color or 0xFF012345.
     * @return The current IconDrawable for chaining.
     */
    fun color(color: Int): IconFontDrawable {
        paint?.color = color
        invalidateSelf()
        return this
    }

    /**
     * Set the color of the drawable.
     *
     * @param colorRes The color resource, from your R file.
     * @return The current IconDrawable for chaining.
     */
    fun colorRes(colorRes: Int): IconFontDrawable {
        paint?.color = ContextCompat.getColor(context!!, colorRes)
        invalidateSelf()
        return this
    }

    /**
     * Set the alpha of this drawable.
     *
     * @param alpha The alpha, between 0 (transparent) and 255 (opaque).
     * @return The current IconDrawable for chaining.
     */
    fun alpha(alpha: Int): IconFontDrawable {
        setAlpha(alpha)
        invalidateSelf()
        return this
    }

    override fun getIntrinsicHeight(): Int {
        return size
    }

    override fun getIntrinsicWidth(): Int {
        return size
    }

    override fun draw(canvas: Canvas) {
        val bounds = bounds
        val height = bounds.height()
        paint?.textSize = height.toFloat()
        val textBounds = Rect()
        val textValue = icon.toString()
        paint?.getTextBounds(textValue, 0, 1, textBounds)
        val textHeight = textBounds.height()
        val textBottom = bounds.top + (height - textHeight) / 2f + textHeight - textBounds.bottom
        canvas.drawText(textValue, bounds.exactCenterX(), textBottom, paint!!)
    }

    override fun isStateful(): Boolean {
        return true
    }

    override fun setState(stateSet: IntArray): Boolean {
        val oldValue = paint?.alpha
        val newValue = if (isEnabled(stateSet)) alphaValue else alphaValue / 2
        paint?.alpha = newValue
        return oldValue != newValue
    }

    override fun setAlpha(alpha: Int) {
        alphaValue = alpha
        paint?.alpha = alpha
    }

    override fun setColorFilter(cf: ColorFilter?) {
        paint?.colorFilter = cf
    }

    override fun clearColorFilter() {
        paint?.colorFilter = null
    }

    @Deprecated("Deprecated in Java", ReplaceWith("alpha"))
    override fun getOpacity(): Int {
        return alpha
    }

    /**
     * Sets paint style.
     *
     * @param style to be applied
     */
    fun setStyle(style: Paint.Style?) {
        paint?.style = style
    }

    // Util
    private fun isEnabled(stateSet: IntArray): Boolean {
        for (state in stateSet) if (state == android.R.attr.state_enabled) return true
        return false
    }
}