package com.dahe.gldriver.weight

import android.animation.ObjectAnimator
import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.app.ActionBar
import android.content.Context
import android.graphics.Color
import android.graphics.drawable.ClipDrawable.HORIZONTAL
import android.graphics.drawable.Drawable
import android.text.*
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.RelativeLayout
import android.widget.TextView
import androidx.core.content.ContextCompat
import com.dahe.gldriver.R
import com.lxj.xpopup.util.KeyboardUtils
import java.security.AccessController.getContext

/**
 * @ClassName VerifyEditText
 * @Author 用户
 * @Date 2024/1/25 09:55
 * @Description TODO
 */
class VerifyEditText @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : LinearLayout(context, attrs, defStyleAttr) {
    private val mTextViewList: MutableList<TextView> = ArrayList()
    private val mRelativeLayouts: MutableList<RelativeLayout> = mutableListOf()
    private val mCursorViews: MutableList<View> = mutableListOf()
    private var mShowCursor = false
    private var mCursorColor: Int = Color.parseColor("#FFFFFF")
    private var mEditText: EditText? = null
    private var drawableNormal: Drawable? = null
    private var drawableSelected: Drawable? = null
    private var mContext: Context? = null
    private var valueAnimator: ValueAnimator? = null
    private var mItemCount = 0

    //输入完成监听
    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.verify_EditText)
        drawableNormal =
            obtainStyledAttributes.getDrawable(R.styleable.verify_EditText_verify_background_normal)
        drawableSelected =
            obtainStyledAttributes.getDrawable(R.styleable.verify_EditText_verify_background_selected)
        val textColor = obtainStyledAttributes.getColor(
            R.styleable.verify_EditText_verify_textColor,
            ContextCompat.getColor(context, android.R.color.black)
        )
        mItemCount = obtainStyledAttributes.getInt(
            R.styleable.verify_EditText_verify_count,
            DEFAULT_ITEM_COUNT
        )
        val inputType = obtainStyledAttributes.getInt(
            R.styleable.verify_EditText_verify_inputType,
            InputType.TYPE_CLASS_NUMBER
        )
        val passwordVisibleTime = obtainStyledAttributes.getInt(
            R.styleable.verify_EditText_verify_password_visible_time,
            DEFAULT_PASSWORD_VISIBLE_TIME
        )
        val width = obtainStyledAttributes.getDimension(
            R.styleable.verify_EditText_verify_width,
            DEFAULT_ITEM_WIDTH.toFloat()
        ).toInt()
        val height =
            obtainStyledAttributes.getDimension(R.styleable.verify_EditText_verify_height, 0f)
                .toInt()
        val cursorWidth = obtainStyledAttributes.getDimension(
            R.styleable.verify_EditText_cursor_width,
            1F
        ).toInt()
        mCursorColor = obtainStyledAttributes.getColor(
            R.styleable.verify_EditText_cursor_color,
            ContextCompat.getColor(context, android.R.color.black)
        )
        mShowCursor =
            obtainStyledAttributes.getBoolean(R.styleable.verify_EditText_show_cursor, false)
        val cursorHeight = obtainStyledAttributes.getDimension(
            R.styleable.verify_EditText_cursor_height,
            20F
        ).toInt()
        val margin = obtainStyledAttributes.getDimension(
            R.styleable.verify_EditText_verify_margin,
            DEFAULT_ITEM_MARGIN.toFloat()
        ).toInt()
        val textSize = px2sp(
            context,
            obtainStyledAttributes.getDimension(
                R.styleable.verify_EditText_verify_textSize,
                sp2px(context, DEFAULT_ITEM_TEXT_SIZE.toFloat()).toFloat()
            )
        ).toFloat()
        val password =
            obtainStyledAttributes.getBoolean(R.styleable.verify_EditText_verify_password, false)
        obtainStyledAttributes.recycle()
        if (mItemCount < 2) mItemCount = 2 //最少 2 个 item
        mEditText = EditText(context)
        mEditText?.run {
            mEditText?.inputType = inputType
            layoutParams = ActionBar.LayoutParams(1, 1)
            isCursorVisible = false
            background = null
            filters = arrayOf<InputFilter>(InputFilter.LengthFilter(mItemCount)) //限制输入长度为 count
            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) {
                    if (before == 0 && (start + count) < 7) {// 输入
                        if (count > 1) {// 有复制内容进来
                            for (i in start until start + count) {
                                val input = s.subSequence(i, i + 1) // 获取新输入的字
                                inputText(i, password, passwordVisibleTime, input.toString())
                            }
                        } else {// 逐步输入
                            inputText(
                                start,
                                password,
                                passwordVisibleTime,
                                s.subSequence(start, s.length).toString()
                            )
                        }
                    } else {// 删除
                        val textView = mTextViewList[start] // 获取对应的 textview
                        textView.text = ""
                        setTextViewBackground(textView, drawableNormal)
                    }
                    if (mInputCompleteListener != null && s.length == mTextViewList.size)
                        mInputCompleteListener?.complete(
                            s.toString()
                        )
                }

                override fun afterTextChanged(s: Editable) {
                    setCursorColor()
                }
            })
        }
        addView(mEditText)
        //点击弹出软键盘
        setOnClickListener { v: View? ->
            mEditText?.requestFocus()
            showSoftKeyBoard()
        }
        //遍历生成 textview
        for (i in 0 until mItemCount) {
            val relativeLayout = RelativeLayout(context)
            relativeLayout.layoutParams = getRelativeLayoutParams(i, margin, width, height)
            mRelativeLayouts.add(relativeLayout)

            val textView = TextView(context)
            textView.textSize = textSize
            textView.maxEms = 1
            textView.maxLines = 1
//            textView.gravity = Gravity.CENTER
            textView.setTextColor(textColor)
//            textView.layoutParams = layoutParams
            initTextView(textView)
            setTextViewBackground(textView, drawableNormal)
//            addView(textView)
            relativeLayout.addView(textView)
            mTextViewList.add(textView)

            if (mShowCursor) {
                val cursorView = View(context)
                initCursorView(cursorView, cursorWidth, cursorHeight)
                relativeLayout.addView(cursorView)
                mCursorViews.add(cursorView)
            }
            relativeLayout.setBackgroundColor(Color.TRANSPARENT)
            addView(relativeLayout)
        }

        setCursorColor()
    }

    private fun getRelativeLayoutParams(
        i: Int,
        margin: Int,
        width: Int,
        height: Int
    ): ActionBar.LayoutParams {
        val layoutParams = ActionBar.LayoutParams(
            width,
            if (height == 0) ViewGroup.LayoutParams.WRAP_CONTENT else height
        )
        if (i == 0) layoutParams.leftMargin = -1 else layoutParams.leftMargin = margin
        return layoutParams
    }

    private fun initTextView(textView: TextView) {
        val lp: RelativeLayout.LayoutParams = RelativeLayout.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.MATCH_PARENT
        )
        textView.gravity = Gravity.CENTER
        textView.layoutParams = lp
    }

    private fun initCursorView(cursorView: View, cursorWidth: Int, cursorHeight: Int) {
        val lp: RelativeLayout.LayoutParams = RelativeLayout.LayoutParams(
            cursorWidth,
            cursorHeight
        )
        lp.addRule(RelativeLayout.ALIGN_PARENT_START)
        lp.addRule(RelativeLayout.CENTER_VERTICAL)
        lp.marginStart = 6
        cursorView.layoutParams = lp
    }

    private fun inputText(start: Int, password: Boolean, passwordVisibleTime: Int, input: String) {
        val textView = mTextViewList[start] // 获取对应的 textview
        textView.text = input
        if (password) { //如果需要密文显示
            textView.transformationMethod =
                HideReturnsTransformationMethod.getInstance()
            //passwordVisibleTime 毫秒后设置为密文显示
            textView.postDelayed(
                {
                    textView.transformationMethod =
                        PasswordTransformationMethod.getInstance()
                },
                passwordVisibleTime.toLong()
            )
        }
        setTextViewBackground(textView, drawableSelected)
    }

    /**
     * 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
    }

    private fun setCursorColor() {
        if (mShowCursor) {
            valueAnimator?.cancel()

            for (i in 0 until mItemCount) {
                val cursorView = mCursorViews[i]
                cursorView.setBackgroundColor(Color.TRANSPARENT)
            }

            val index = mEditText?.text?.length ?: 0
            if (index < mItemCount) {
                setCursorView(mCursorViews[index])
            }
        }
    }

    /**
     * 设置焦点色变换动画
     *
     * @param view
     */
    private fun setCursorView(view: View) {
        this.valueAnimator = ObjectAnimator.ofInt(
            view,
            "backgroundColor",
            mCursorColor,
            android.R.color.transparent
        )
        valueAnimator?.run {
            duration = 1500
            repeatCount = -1
            repeatMode = ValueAnimator.RESTART
            setEvaluator { fraction, startValue, endValue -> if (fraction <= 0.5f) startValue else endValue }
            start()
        }
    }

    /**
     * 获取当前输入的内容
     *
     * @return
     */
    val content: String
        get() {
            val text = mEditText?.text
            return if (TextUtils.isEmpty(text)) "" 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 = Math.min(chars.size, 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()
    }

    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        KeyboardUtils.hideSoftInput(this)
//        CommonUtil.hideKeyboard(this)
        valueAnimator?.cancel()
    }


    companion object {
        //默认 item 个数为 4 个
        private const val DEFAULT_ITEM_COUNT = 4

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

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

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

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