<template>
    <div v-if="pageIsReadOnly && readValue">
        <a-input class="dhc-ProInputNumber" :type="type" :controls="false" controls-position="right" v-bind="$attrs"
            v-model:value="readValComp" :disabled="true" />
    </div>
    <div v-else>
        <a-input-number v-if="type !== 'amt'" class="dhc-ProInputNumber" v-model:value="sValue" :controls="false"
            controls-position="right" @change="handleChange" @focus="handleFocus" @blur="handleBlur" v-bind="$attrs"
            v-suffix :max="sMax" :min="sMin" :precision="setPrecision ? precision : undefined" :type="type"
            :disabled=disabled></a-input-number>
        <a-input-number ref="amtInput" v-if="type === 'amt'" class="dhc-ProInputNumber" v-model:value="sValue"
            :controls="false" controls-position="right" @change="handleChange" @focus="handleFocus" @blur="handleBlur"
            v-bind="$attrs" v-thousands :max="sMax" :min="sMin" :precision="setPrecision ? precision : undefined"
            @paste.native="handlePaste" :disabled=disabled>
        </a-input-number>
    </div>
</template>
<script>
import { amtFormatter } from '@/utils/util.ts'
import { removeComma } from '@/utils/validate.js'
import { isEmpty } from '@/utils/validate'
/**
 * 后缀集合
 */
const suffixs = {
    percent: '%'
}
/**
 *  设置后缀
 * @param {*} el
 * @param {*} binding
 * @param {*} vnode
 * @param {*} oldVnode
 */
const setSuffix = (el, binding, vnode, oldVnode) => {
    let { type } = vnode.data.attrs
    if (type) {
        let suffix = suffixs[type]
        if (suffix == undefined) {
            return
        }
        // 获取input节点
        if (el.tagName.toLocaleUpperCase() !== 'INPUT') {
            el = el.getElementsByTagName('input')[0]
        }
        // 转化成异步，否则无法拿到更新后的el.value的值
        let timer = setTimeout(() => {
            // 清空时给个默认值为0
            if (el.value == undefined || el.value == null) return el.value = ''
            if (el.value.indexOf(suffix) > -1) {
                el.value = el.value
            } else {
                el.value = el.value + suffix
            }
            clearTimeout(timer)
        }, 0)
        // 转化为数字格式（去除千分位）
        el.onfocus = e => {
            clearTimeout(timer)
            el.value = el.value.replace(suffix, "")
        }
        // 转化为三位一逗格式（添加千分位）
        el.onblur = e => {
            clearTimeout(timer)
            // 清空时给个默认值为0
            if (el.value == undefined || el.value == null) return el.value = ''
            if (el.value.indexOf(suffix) > -1) {
                el.value = el.value
            } else {
                el.value = el.value + suffix
            }
        }
    }
}
export default {
    name: 'ProInputNumber',
    props: {
        readValue: {
            type: [Number, String],
            default: null
        },
        value: {
            type: [Number, String],
            default: 0
        },
        type: String,    //amt:三位一逗;percent:百分比
        max: {
            type: Number
        },
        min: {
            type: Number
        },
        precision: {
            type: Number,
            default: 0
        },
        disabled: {
            type: Boolean,
            default: false
        },
        setPrecision: {
            type: Boolean,
            default: true
        },
        readIgnore: {
            type: String,
            default: null
        }
    },
    inject: {
        pageIsReadOnly: {
            default: false
        },
    },
    data () {
        let sMax = this.max
        let sMin = this.min
        //百分比自动设置最大最小值
        if (this.type == "percent") {
            sMax ? "" : sMax = 100
            sMin ? "" : sMin = 0
        } else {
            // 获取max
            let maxTemp = this.getMax()
            if (isEmpty(sMax) || isNaN(sMax)) {
                sMax = maxTemp
            }
            if (isEmpty(sMin) || isNaN(sMax)) {
                sMin = -maxTemp
            }
        }
        return {
            sValue: this.value,
            sMax: sMax,
            sMin: sMin,
            //正在粘贴标志
            parsing: false
        }
    },
    computed: {
        readValComp () {
            if (this.type) {
                if (suffixs[this.type]) {
                    return this.readValue + suffixs[this.type]
                }
            }
            return this.readValue
        }
    },
    watch: {
        value: {
            handler (val, oldVal) {
                if (val != oldVal) {
                    this.sValue = val
                }
            }
        },
        //判断值是否有改变
        sValue: {
            handler (val, oldVal) {
                if (val != oldVal) {
                    this.$emit('input', val)

                }
            }
        },
        max: {
            immediate: true,
            handler (val, oldVal) {
                if (!isEmpty(val)) {
                    let sMax = val
                    //百分比自动设置最大最小值
                    if (this.type == "percent") {
                        sMax ? "" : sMax = 100
                    } else {
                        // 获取max
                        let maxTemp = this.getMax()
                        if (isEmpty(sMax) || isNaN(sMax)) {
                            sMax = maxTemp
                        }
                        this.sMax = sMax
                    }
                    // 如果绑定值超过最大值，强制将其设置为最大值
                    if (this.sValue > sMax) {
                        this.sValue = sMax
                    }
                }
            }
        },
        min: {
            immediate: true,
            handler (val, oldVal) {
                if (!isEmpty(val)) {
                    let sMin = val
                    //百分比自动设置最大最小值
                    if (this.type == "percent") {
                        sMin ? "" : sMin = 100
                    } else {
                        // 获取max
                        let maxTemp = this.getMax()
                        if (isEmpty(sMin) || isNaN(sMin)) {
                            sMin = - maxTemp
                        }
                        this.sMin = sMin
                    }
                    // 如果绑定值小于最小值，强制将其设置为最小值
                    if (this.sValue < sMin) {
                        this.sValue = sMin
                    }
                }
            }
        },
    },
    methods: {
        //绑定值被改变时的回调
        handleChange (currentValue, oldValue) {
            this.$emit('change', currentValue, oldValue)
        },
        //组件 Input 失去焦点时触发
        handleFocus (event) {
            this.$emit('focus', event)
        },
        //组件 Input 获得焦点时触发
        handleBlur (e) {
            this.$emit('blur', e)
        },
        //暴露给组件外使用
        getMax () {
            //如果有值则直接返回
            if (!isEmpty(this.sMax) && !isNaN(this.sMax)) {
                return this.sMax
            }
            // 限制为整数和小数一共十五位，否则会有精度损失
            //2位小数，整数支持13位（15,2），3位小数，整数支持12位（15,3）
            let precision = this.precision
            if (precision != 0) {
                let integerPart = 9
                let integerPartRes = 0
                let fractionalPart = 0.9
                let fractionalPartRes = 0.9
                for (let index = 0; index < 15 - precision; index++) {
                    integerPartRes += integerPart
                    integerPart *= 10
                }
                for (let index = 0; index < precision - 1; index++) {
                    fractionalPart /= 10
                    fractionalPartRes += fractionalPart
                }
                return integerPartRes + fractionalPartRes
            } else {
                //如果精度为0，设置最大值为14个9，与数据库的（16，2）保持统一
                return 99999999999999
            }

        },
        //暴露给组件外使用
        getMin () {
            return this.sMin
        },
        handlePaste (event) {
            let that = this
            //禁用时不粘贴
            if (!this.disabled) {
                let regex = /^[0-9,]+$/;
                const clipboardData = event.clipboardData || window.clipboardData
                //获取剪贴板中的纯文本内容
                const pastedText = clipboardData.getData('text/plain')
                //如果为数字和‘,’，则允许粘贴且触发change事件
                if (regex.test(pastedText)) {
                    setTimeout(() => {
                        this.sValue = parseFloat(pastedText.replace(/,/g, ''))
                        that.parsing = true
                        //解决粘贴不触发change事件的bug
                        that.$emit('change', this.sValue)
                    }, 100)
                }
            }
        },
    },
    //自定义指令
    directives: {
        //定义指令名v-thousands
        thousands: {
            // 所在组件的 VNode 更新时调用
            update: function (el, binding, vnode, oldVnode) {
                // 获取input节点
                if (el.tagName.toLocaleUpperCase() !== 'INPUT') {
                    el = el.getElementsByTagName('input')[0]
                }
                // 转化成异步，否则无法拿到更新后的el.value的值
                let timer = setTimeout(() => {
                    // 清空时给个默认值为0
                    if (el.value == undefined || el.value == null) return el.value = ''
                    //如果是粘贴触发，则不进行格式化，防止出现数据为上一次的问题
                    if (vnode.context?.parsing) {
                        vnode.context.parsing = false
                    } else {
                        el.value = amtFormatter(el.value)
                    }
                    clearTimeout(timer)
                }, 0)
                // 转化为数字格式（去除千分位）
                el.onfocus = e => {
                    clearTimeout(timer)
                    el.value = removeComma(el.value)
                }
                // 转化为三位一逗格式（添加千分位）
                el.onblur = e => {
                    clearTimeout(timer)
                    // 清空时给个默认值为0
                    if (el.value == undefined || el.value == null) return el.value = ''
                    el.value = amtFormatter(el.value)
                }
            }
        },
        //添加后缀
        suffix: {
            inserted: function (el, binding, vnode, oldVnode) {
                setSuffix(el, binding, vnode, oldVnode)
            },
            // 所在组件的 VNode 更新时调用
            update: function (el, binding, vnode, oldVnode) {
                setSuffix(el, binding, vnode, oldVnode)
            },

        },
    },
}
</script>
<style lang="less" scoped>
.dhc-ProInputNumber {
    width: 100%;

    ::v-deep .a-input input {
        text-align: right;
    }
}
</style>
