package com.keyboard.journey.view

import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Typeface
import android.graphics.drawable.Drawable
import android.util.AttributeSet
import androidx.core.content.ContextCompat
import androidx.core.graphics.drawable.DrawableCompat
import com.keyboard.journey.R
import com.keyboard.journey.view.JourneyKeyboardView.Config.Companion.KEYCODE_BACK
import com.keyboard.journey.view.JourneyKeyboardView.Config.Companion.KEYCODE_CANCEL
import com.keyboard.journey.view.JourneyKeyboardView.Config.Companion.KEYCODE_DELETE
import com.keyboard.journey.view.JourneyKeyboardView.Config.Companion.KEYCODE_DONE
import com.keyboard.journey.view.JourneyKeyboardView.Config.Companion.KEYCODE_DOT
import com.keyboard.journey.view.JourneyKeyboardView.Config.Companion.KEYCODE_MODE_BACK
import com.keyboard.journey.view.JourneyKeyboardView.Config.Companion.KEYCODE_MODE_CHANGE
import com.keyboard.journey.view.JourneyKeyboardView.Config.Companion.KEYCODE_MORE
import com.keyboard.journey.view.JourneyKeyboardView.Config.Companion.KEYCODE_NONE
import com.keyboard.journey.view.JourneyKeyboardView.Config.Companion.KEYCODE_QUESTION_MARK
import com.keyboard.journey.view.JourneyKeyboardView.Config.Companion.KEYCODE_SPACE

open class JourneyKeyboardView : KeyboardView {


    private var isCap = false

    private var isAllCaps = false

    private lateinit var config: Config

    private val paint by lazy { Paint() }

    companion object {
        const val iconRatio = 0.5f

    }


    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
        init(context, attrs)
    }

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

    constructor(
        context: Context,
        attrs: AttributeSet?,
        defStyleAttr: Int,
        defStyleRes: Int
    ) : super(context, attrs, defStyleAttr, defStyleRes) {
        init(context, attrs)
    }


    private fun init(context: Context, attrs: AttributeSet?) {
        config = Config(context)

        var a = context.obtainStyledAttributes(attrs, R.styleable.journeyKeyboardView)

        a.indexCount.let {
            config.run {
                for (i in 0 until it) {
                    when (val attr = a.getIndex(i)) {
                        R.styleable.journeyKeyboardView_kkbDeleteDrawable -> deleteDrawable =
                            a.getDrawable(attr)

                        R.styleable.journeyKeyboardView_kkbCapitalDrawable -> capitalDrawable =
                            a.getDrawable(attr)

                        R.styleable.journeyKeyboardView_kkbCapitalLockDrawable -> capitalLockDrawable =
                            a.getDrawable(attr)
                        
                        R.styleable.journeyKeyboardView_android_labelTextSize -> labelTextSize =
                            a.getDimensionPixelSize(attr, labelTextSize)

                        R.styleable.journeyKeyboardView_android_keyTextSize -> keyTextSize =
                            a.getDimensionPixelSize(attr, keyTextSize)

                        R.styleable.journeyKeyboardView_android_keyTextColor -> keyTextColor =
                            a.getColor(attr, keyTextColor)

                        R.styleable.journeyKeyboardView_kkbKeyIconColor -> keyIconColor = a.getColor(
                            attr,
                            ContextCompat.getColor(context, R.color.journey_keyboard_key_icon_color)
                        )

                        R.styleable.journeyKeyboardView_kkbKeySpecialTextColor -> keySpecialTextColor =
                            a.getColor(attr, keySpecialTextColor)

                        R.styleable.journeyKeyboardView_kkbKeyDoneTextColor -> keyDoneTextColor =
                            a.getColor(attr, keyDoneTextColor)

                        R.styleable.journeyKeyboardView_kkbKeyNoneTextColor -> keyNoneTextColor =
                            a.getColor(attr, keyNoneTextColor)

                        R.styleable.journeyKeyboardView_android_keyBackground -> keyBackground =
                            a.getDrawable(attr)

                        R.styleable.journeyKeyboardView_kkbSpecialKeyBackground -> specialKeyBackground =
                            a.getDrawable(attr)

                        R.styleable.journeyKeyboardView_kkbDoneKeyBackground -> doneKeyBackground =
                            a.getDrawable(attr)

                        R.styleable.journeyKeyboardView_kkbNoneKeyBackground -> noneKeyBackground =
                            a.getDrawable(attr)

                        R.styleable.journeyKeyboardView_kkbKeyDoneTextSize -> keyDoneTextSize =
                            a.getDimensionPixelSize(attr, keyDoneTextSize)

                        R.styleable.journeyKeyboardView_kkbKeyDoneText -> keyDoneText =
                            a.getString(attr)
                    }
                }
            }
            a.recycle()
        }

        paint.textAlign = Paint.Align.CENTER
        paint.isAntiAlias = true

    }

    fun getConfig(): Config {
        return config
    }

    fun setConfig(config: Config) {
        this.config = config
        invalidate()
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        drawKeyboard(canvas, keyboard?.keys)
    }

    /**
     * 绘制键盘
     */
    private fun drawKeyboard(canvas: Canvas, keys: List<Keyboard.Key>?) {
        keys?.let {
            for (key in it) {
                drawKey(canvas, key)
            }
        }
    }

    /**
     * 绘制键盘按键
     */
    private fun drawKey(canvas: Canvas, key: Keyboard.Key) {
        when (key.codes[0]) {
            Keyboard.KEYCODE_SHIFT -> drawShiftKey(canvas, key)
            KEYCODE_MODE_CHANGE -> drawKey(
                canvas,
                key,
                config.toggleKeyBackground,
                config.toggleKeyTextColor
            )

            KEYCODE_CANCEL -> drawCancelKey(canvas, key)
            KEYCODE_DONE -> drawDoneKey(canvas, key)
            KEYCODE_DELETE -> drawDeleteKey(canvas, key)
            KEYCODE_SPACE ->
                config.keySpecialText.let {
                    key.label = it
                    drawKey(
                        canvas,
                        key,
                        config.toggleKeyBackground,
                        config.toggleKeyTextColor,
                        null
                    )
                }

            KEYCODE_DOT->{
                drawKey(
                    canvas,
                    key,
                    config.toggleKeyBackground,
                    config.toggleKeyTextColor,
                    null
                )
            }
            KEYCODE_QUESTION_MARK->{
                drawKey(
                    canvas,
                    key,
                    config.toggleKeyBackground,
                    config.toggleKeyTextColor,
                    null
                )
            }
            KEYCODE_NONE -> drawNoneKey(canvas, key)
            KEYCODE_MODE_BACK -> drawKey(
                canvas,
                key,
                config.toggleKeyBackground,
                config.toggleKeyTextColor
            )

            KEYCODE_BACK -> drawKey(
                canvas,
                key,
                config.toggleKeyBackground,
                config.toggleKeyTextColor
            )

            KEYCODE_MORE -> drawKey(
                canvas,
                key,
                config.toggleKeyBackground,
                config.toggleKeyTextColor
            )

            in -399..-300 -> drawKey(
                canvas,
                key,
                config.toggleKeyBackground,
                config.keyTextColor
            )

            else -> drawKey(canvas, key, config.keyBackground, config.keyTextColor)
        }
    }

    private fun drawCancelKey(canvas: Canvas, key: Keyboard.Key) {
        config.keyDoneText?.let {
            key.label = it
        }
        drawKey(canvas, key, config.toggleKeyBackground, config.toggleKeyTextColor, null, true)
    }

    private fun drawDoneKey(canvas: Canvas, key: Keyboard.Key) {
        config.keyDoneText?.let {
            key.label = it
        }
        drawKey(canvas, key, config.toggleKeyBackground, config.toggleKeyTextColor, null, true)
    }

    private fun drawNoneKey(canvas: Canvas, key: Keyboard.Key) {
        drawKey(canvas, key, config.noneKeyBackground, config.keyNoneTextColor)
    }

    private fun drawDeleteKey(canvas: Canvas, key: Keyboard.Key) {
        drawKey(
            canvas,
            key,
            config.toggleKeyBackground,
            config.keySpecialTextColor,
            config.deleteDrawable
        )
    }

    private fun drawShiftKey(canvas: Canvas, key: Keyboard.Key) {
        when {
            isAllCaps -> drawKey(
                canvas,
                key,
                config.toggleKeyBackground,
                config.keySpecialTextColor,
                config.capitalLockDrawable
            )

            isCap -> drawKey(
                canvas,
                key,
                config.toggleKeyBackground,
                config.keySpecialTextColor,
                config.capitalDrawable
            )

            else -> drawKey(
                canvas,
                key,
                config.toggleKeyBackground,
                config.keySpecialTextColor,
                config.lowerDrawable
            )
        }
    }

    /**
     * 绘制键盘按键
     */
    private fun drawKey(
        canvas: Canvas,
        key: Keyboard.Key,
        keyBackground: Drawable?,
        textColor: Int,
        iconDrawable: Drawable? = key.icon,
        isDone: Boolean = false
    ) {
        //绘制按键背景
        keyBackground?.run {
            if (key.codes[0] != 0) {
                state = key.currentDrawableState
            }

            setBounds(
                key.x.plus(paddingLeft),
                key.y.plus(paddingTop),
                key.x.plus(paddingLeft).plus(key.width),
                key.y.plus(paddingTop).plus(key.height)
            )
            draw(canvas)
        }

        //绘制键盘图标
        iconDrawable?.run {

            val drawable = DrawableCompat.wrap(this)
            config.keyIconColor?.takeIf { it != 0 }?.let {
                drawable.setTint(it)
            }

            key.icon = drawable

            var iconWidth = key.icon.intrinsicWidth.toFloat()
            var iconHeight = key.icon.intrinsicHeight.toFloat()

            val widthRatio = iconWidth.div(key.width.toFloat())
            val heightRatio = iconHeight.div(key.height.toFloat())

            if (widthRatio <= heightRatio) {//当图标的宽占比小于等于高占比时，以高度比例为基准并控制在iconRatio比例范围内，进行同比例缩放

                val ratio = heightRatio.coerceAtMost(iconRatio)
                iconWidth = iconWidth.div(heightRatio).times(ratio)
                iconHeight = iconHeight.div(heightRatio).times(ratio)

            } else {//反之，则以宽度比例为基准并控制在iconRatio比例范围内，进行同比例缩放

                val ratio = widthRatio.coerceAtMost(iconRatio)
                iconWidth = iconWidth.div(widthRatio).times(ratio)
                iconHeight = iconHeight.div(widthRatio).times(ratio)

            }

            val left = key.x.plus(paddingLeft).plus(key.width.minus(iconWidth).div(2f)).toInt()
            val top = key.y.plus(paddingTop).plus(key.height.minus(iconHeight).div(2f)).toInt()
            val right = left.plus(iconWidth).toInt()
            val bottom = top.plus(iconHeight).toInt()
            key.icon.setBounds(left, top, right, bottom)
            key.icon.draw(canvas)

        } ?: key.label?.let {
            //绘制键盘文字
            if (isDone) {
                paint.textSize = config.keyDoneTextSize.toFloat()
            } else if (it.length > 1 && key.codes.size < 2) {// 键盘key内容多个字符
                paint.textSize = config.labelTextSize.toFloat()
            } else {
                paint.textSize = config.keyTextSize.toFloat()
            }
            paint.color = textColor
            paint.typeface = Typeface.DEFAULT

            canvas.drawText(
                it.toString(),
                key.x.plus(paddingLeft).plus(key.width.div(2f)),
                key.y.plus(paddingTop).plus(key.height.div(2.0f)).plus(
                    paint.textSize.minus(paint.descent()).div(2.0f)
                ),
                paint
            )

        }

    }


    fun setCap(isCap: Boolean) {
        this.isCap = isCap
    }

    fun isCap(): Boolean {
        return isCap
    }

    fun setAllCaps(isAllCaps: Boolean) {
        this.isAllCaps = isAllCaps
    }

    fun isAllCaps(): Boolean {
        return isAllCaps
    }

    /**
     * Config为journeyKeyboard的配置类，方便统一管理配置信息
     */
    open class Config(context: Context) {

        var deleteDrawable = context.getDrawable(R.drawable.delete_key_background)
        var lowerDrawable = context.getDrawable(R.mipmap.sym_keyboard_shift)
        var capitalDrawable = context.getDrawable(R.mipmap.sym_keyboard_shift)
        var capitalLockDrawable = context.getDrawable(R.mipmap.sym_keyboard_shift_locked)

        var labelTextSize =
            context.resources.getDimensionPixelSize(R.dimen.journey_keyboard_label_text_size)

        var keyTextSize = context.resources.getDimensionPixelSize(R.dimen.journey_keyboard_text_size)

        var keyTextColor = ContextCompat.getColor(context, R.color.purple_200)

        var keyIconColor: Int? = null

        var keySpecialTextColor =
            ContextCompat.getColor(context, R.color.purple_500)

        var keyDoneTextColor =
            ContextCompat.getColor(context, R.color.purple_700)

        var keyNoneTextColor =
            ContextCompat.getColor(context, R.color.teal_200)

        var keyBackground = context.getDrawable(R.drawable.key_background)

        var specialKeyBackground = context.getDrawable(R.drawable.key_background)

        var toggleKeyBackground = context.getDrawable(R.drawable.key_background)

        var toggleKeyTextColor = ContextCompat.getColor(context, R.color.purple_500)

        var doneKeyBackground = context.getDrawable(R.drawable.key_background)
        var noneKeyBackground = context.getDrawable(R.drawable.key_background)

        var keyDoneTextSize =
            context.resources.getDimensionPixelSize(R.dimen.journey_keyboard_done_text_size)

        var keyDoneText: CharSequence? = context.getString(R.string.journey_keyboard_key_done_text)


        var keySpecialText: CharSequence? = "English"

        companion object{

            /**
             * Shift键 -> 一般用来切换键盘大小写字母
             */
            const val KEYCODE_SHIFT = -1
            /**
             * 模式改变 -> 切换键盘输入法
             */
            const val KEYCODE_MODE_CHANGE = -2
            /**
             * 取消键 -> 关闭输入法
             */
            const val KEYCODE_CANCEL = -3
            /**
             * 完成键 -> 长出现在右下角蓝色的完成按钮
             */
            const val KEYCODE_DONE = -4
            /**
             * 删除键 -> 删除输入框内容
             */
            const val KEYCODE_DELETE = -5
            /**
             * 空格键
             */
            const val KEYCODE_SPACE = 32

            const val KEYCODE_DOT = 46

            const val KEYCODE_QUESTION_MARK = 63

            /**
             * 无作用键 -> 一般用来占位或者禁用按键
             */
            const val KEYCODE_NONE = 0

            /**
             * 键盘按键 -> 返回（返回，适用于切换键盘后界面使用，如：NORMAL_MODE_CHANGE或CUSTOM_MODE_CHANGE键盘）
             */
            const val KEYCODE_MODE_BACK = -101

            /**
             * 键盘按键 ->返回（直接返回到最初,直接返回到NORMAL或CUSTOM键盘）
             */
            const val KEYCODE_BACK = -102

            /**
             * 键盘按键 ->更多
             */
            const val KEYCODE_MORE = -103
        }
    }
    
}