package com.abbidot.tracker.widget

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.drawable.Drawable
import android.text.*
import android.text.InputFilter.LengthFilter
import android.text.method.HideReturnsTransformationMethod
import android.text.method.PasswordTransformationMethod
import android.util.AttributeSet
import android.view.Gravity
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager
import android.widget.EditText
import android.widget.LinearLayout
import android.widget.TextView
import androidx.core.content.ContextCompat
import com.abbidot.tracker.R
import com.abbidot.tracker.util.ViewUtil
import java.util.*

/**
 * Created by SongSenior on 2021/4/16
 * 一个 EditText 和 n 个 TextView
 */
class VerifyEditText @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : LinearLayout(context, attrs, defStyleAttr) {
    private val mTextViewList: MutableList<TextView> = ArrayList()
    private var mEditText: EditText? = null
    private var drawableNormal: Drawable? = null
    private var drawableSelected: Drawable? = null
    private var mContext: Context? = null

    //默认 item 个数为 4 个
    private val mDefaultItemCount = 4

    //默认每个 item 的宽度为 100
    private val mDefaultItemWidth = 100

    //默认每个 item 的间距为 50
    private val mDefaultItemMargin = 50

    //默认每个 item 的字体大小为 14
    private val mDefaultItemTextSize = 14

    //默认密码明文显示时间为 200ms，之后密文显示
    private val mDefaultPasswordVisibleTime = 200

    //是否大小写
    private var mCapitalLetter = false

    //监听编辑输入事件
    private var mOnEditClickListener: OnClickListener? = null
    //输入完成监听
    private var mInputCompleteListener: InputCompleteListener? = null

    init {
        init(context, attrs)
    }

    private fun init(context: Context, attrs: AttributeSet?) {
        mContext = context
        orientation = HORIZONTAL
        gravity = Gravity.CENTER
        @SuppressLint("CustomViewStyleable") val obtainStyledAttributes =
            getContext().obtainStyledAttributes(attrs, R.styleable.VerifyEditText)
        drawableNormal =
            obtainStyledAttributes.getDrawable(R.styleable.VerifyEditText_verify_background_normal)
        drawableSelected = obtainStyledAttributes.getDrawable(
            R.styleable.VerifyEditText_verify_background_selected
        )
        val textColor = obtainStyledAttributes.getColor(
            R.styleable.VerifyEditText_verify_textColor,
            ContextCompat.getColor(context, android.R.color.black)
        )
        val verifyTypeface =
            obtainStyledAttributes.getString(R.styleable.VerifyEditText_verify_typeface)
        val typeface = ViewUtil.instance.setTypeface(context, verifyTypeface)

        var count = obtainStyledAttributes.getInt(
            R.styleable.VerifyEditText_verify_count, mDefaultItemCount
        )
        val inputType = obtainStyledAttributes.getInt(
            R.styleable.VerifyEditText_verify_inputType, InputType.TYPE_CLASS_NUMBER
        )
        val passwordVisibleTime = obtainStyledAttributes.getInt(
            R.styleable.VerifyEditText_verify_password_visible_time, mDefaultPasswordVisibleTime
        )
        val width = obtainStyledAttributes.getDimension(
            R.styleable.VerifyEditText_verify_width, mDefaultItemWidth.toFloat()
        ).toInt()
        val height =
            obtainStyledAttributes.getDimension(R.styleable.VerifyEditText_verify_height, 0f)
                .toInt()
        val margin = obtainStyledAttributes.getDimension(
            R.styleable.VerifyEditText_verify_margin, mDefaultItemMargin.toFloat()
        ).toInt()
        val textSize = px2sp(
            context, obtainStyledAttributes.getDimension(
                R.styleable.VerifyEditText_verify_textSize,
                sp2px(context, mDefaultItemTextSize.toFloat()).toFloat()
            )
        ).toFloat()
        val password =
            obtainStyledAttributes.getBoolean(R.styleable.VerifyEditText_verify_password, false)
        mCapitalLetter =
            obtainStyledAttributes.getBoolean(R.styleable.VerifyEditText_capital_letter, false)
        obtainStyledAttributes.recycle()
        if (count < 2) count = 2 //最少 2 个 item
        mEditText = EditText(context)
        mEditText!!.inputType = inputType
        mEditText!!.layoutParams = LayoutParams(1, 1)
        mEditText!!.isCursorVisible = false
        mEditText!!.background = null
        mEditText!!.filters = arrayOf<InputFilter>(LengthFilter(count)) //限制输入长度为 count
        mEditText!!.addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
            override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
                val textView = mTextViewList[start] //获取对应的 textview
                if (before == 0) {
                    //输入
                    val input = s.subSequence(start, s.length)
                    //获取新输入的字
                    textView.text = if (mCapitalLetter) {
                        //字母转换为大写
                        input.toString().uppercase(Locale.getDefault())
                    } else {
                        input
                    }

                    if (password) { //如果需要密文显示
                        textView.transformationMethod =
                            HideReturnsTransformationMethod.getInstance()
                        //passwordVisibleTime 毫秒后设置为密文显示
                        textView.postDelayed({
                            textView.transformationMethod =
                                PasswordTransformationMethod.getInstance()
                        }, passwordVisibleTime.toLong())
                    }
                    setTextViewBackground(textView, drawableSelected)
                } else {
                    //删除
                    textView.text = ""
                    setTextViewBackground(textView, drawableNormal)
                }
                if (mInputCompleteListener != null && s.length == mTextViewList.size) mInputCompleteListener!!.complete(
                    s.toString()
                )
                mOnEditClickListener?.onClick(this@VerifyEditText)
            }

            override fun afterTextChanged(s: Editable) {}
        })
        addView(mEditText)
        //点击弹出软键盘
        setOnClickListener { v: View? ->
            mEditText!!.requestFocus()
            showSoftKeyBoard()
        }
        //遍历生成 textview
        for (i in 0 until count) {
            val textView = TextView(context)
            textView.textSize = textSize
            textView.filters = arrayOf(LengthFilter(1))
            textView.gravity = Gravity.CENTER
            textView.setTextColor(textColor)
            textView.typeface = typeface
            val layoutParams = LayoutParams(
                width, if (height == 0) ViewGroup.LayoutParams.WRAP_CONTENT else height
            )
            if (i == 0) layoutParams.leftMargin = -1 else layoutParams.leftMargin = margin
            textView.layoutParams = layoutParams
            setTextViewBackground(textView, drawableNormal)
            addView(textView)
            mTextViewList.add(textView)
        }
    }

    /**
     * view 添加到窗口时，延迟 500ms 弹出软键盘
     */
    override fun onAttachedToWindow() {
        super.onAttachedToWindow()
        mEditText!!.postDelayed({ showSoftKeyBoard() }, 500)
    }

    /**
     * 设置背景
     *
     * @param textView
     * @param drawable
     */
    private fun setTextViewBackground(textView: TextView, drawable: Drawable?) {
        if (drawable != null) textView.background = drawable
    }

    /**
     * 设置背景颜色
     */
    fun setBoxBackground(drawable: Drawable?) {
        for (textView in mTextViewList) {
            setTextViewBackground(textView, drawable)
        }
    }

    fun setEditClickListener(onClickListener: OnClickListener) {
        mOnEditClickListener = onClickListener
    }

    /**
     * 获取当前输入的内容
     *
     * @return
     */
    val content: String
        get() {
            val text = mEditText!!.text
            return if (TextUtils.isEmpty(text)) "" else {
                if (mCapitalLetter) {
                    //字母转换为大写
                    mEditText!!.text.toString().uppercase(Locale.getDefault())
                } else mEditText!!.text.toString()
            }
        }

    /**
     * 清除内容
     */
    fun clearContent() {
        mEditText!!.setText("")
        for (i in mTextViewList.indices) {
            val textView = mTextViewList[i]
            textView.text = ""
            setTextViewBackground(textView, drawableNormal)
        }
    }

    /**
     * 设置默认的内容
     *
     * @param content
     */
    fun setDefaultContent(content: String) {
        mEditText!!.setText(content)
        mEditText!!.requestFocus()
        val chars = content.toCharArray()
        val min = chars.size.coerceAtMost(mTextViewList.size)
        for (i in 0 until min) {
            val aChar = chars[i]
            val s = aChar.toString()
            val textView = mTextViewList[i]
            textView.text = s
            setTextViewBackground(textView, drawableSelected)
        }
        if (mInputCompleteListener != null && min == mTextViewList.size) mInputCompleteListener!!.complete(
            content.substring(0, min)
        )
    }

    /**
     * 显示软键盘
     */
    private fun showSoftKeyBoard() {
        val imm = mContext!!.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
        imm.showSoftInput(mEditText, InputMethodManager.SHOW_FORCED)
    }

    /**
     * 添加输入完成的监听
     *
     * @param inputCompleteListener
     */
    fun addInputCompleteListener(inputCompleteListener: InputCompleteListener?) {
        mInputCompleteListener = inputCompleteListener
        val content = mEditText!!.text
        if (!TextUtils.isEmpty(content) && content.toString().length == mTextViewList.size) {
            mInputCompleteListener!!.complete(content.toString())
        }
    }

    interface InputCompleteListener {
        fun complete(content: String?)
    }

    private fun px2sp(context: Context, pxValue: Float): Int {
        val fontScale = context.resources.displayMetrics.scaledDensity
        return (pxValue / fontScale + 0.5f).toInt()
    }

    private fun sp2px(context: Context, spValue: Float): Int {
        val fontScale = context.resources.displayMetrics.scaledDensity
        return (spValue * fontScale + 0.5f).toInt()
    }

}