<template>
    <div class="nus_number">
        <span class="nu_number-btn nu_minus nu_icon"
            :class="{'nu_number-disable': isMin}"
            @click="_addSub(true)">{{ minusIcon }}
        </span><nu-input
            class="nu_number-input"
            v-model="myValue"
            v-on="$listeners"
            :type="isDecimal ? 'text' : 'number'"
            :isNumber="isDecimal"
            :readonly="!isEdit"
            :keyDownFilter="_keyDown"
            :sufIcon="''"
            @blur="_onBlur">
        </nu-input><span class="nu_number-btn nu_add nu_icon"
            :class="{'nu_number-disable': isMax}"
            @click="_addSub()">
            {{ addIcon }}
        </span>
    </div>
</template>

<script>
import FormTmp from '../_comm/FormTmp';
import vModel from '../../../Mixins/vModel';
import NuInput from '../input/Input';
export default {
    extends: FormTmp,
    name: 'NuNumber',
    props: {
        /**
         * 增加的图标
         */
        addIcon: {
            default: '\ue618'
        },
        /**
         * 减少的图标
         */
        minusIcon: {
            default: '\ue619'
        },
        /**
         * 最大数字
         */
        maxNum: {},
        /**
         * 最小数字
         */
        minNum: {},
        /**
         * 每次增加／减少的数量
         */
        step: {
            type: Number
        },
        /**
         * 是否要编辑
         */
        isEdit: {
            type: Boolean,
            default: true
        },
        /**
         * 是否支持小数
         */
        isDecimal: {
            type: Boolean,
            default: false
        }
    },
    computed: {
        /**
         * 最小值
         * @returns {Numbar|null}
         */
        myMinNum() {
            return this._toNumber(this.minNum);
        },
        /**
         * 最大值
         * @returns {Numbar|null}
         */
        myMaxNum() {
            return this._toNumber(this.maxNum);
        }
    },
    components: {
        NuInput
    },
    data () {
        return {
            isMin: false, // 是否是最小
            isMax: false // 是否是最大
        };
    },
    mixins: [vModel({
        value: {
            default: 1
        },
        /**
         * 监听表单的值
         * @param {String} nowVal 表单值
         */
        myValueChange(nowVal) {
            const _that = this;
            setTimeout(() => {
                _that._setValue(nowVal);
            }, 0);
        }
    })],
    watch: {
        /**
         * 监听最小值
         * @param {Number} nowVal 最小值
         */
        myMinNum () {
            this._setValue(this.myValue);
        },
        /**
         * 监听最大值
         * @param {Number} nowVal 最大值
         */
        myMaxNum () {
            this._setValue(this.myValue);
        }
    },
    created() {
        this._setValue(this.mValue);
    },
    methods: {
        /**
         * 禁用按键
         * @param {Object} data 数据
         * @returns {boolean}
         */
        _keyDown(data) {
            let _that = this;
            let isMin = _that.myValue <= _that.myMinNum;
            let isMax = _that.myValue >= _that.myMaxNum;
            let keyCode = data && data.keyCode;
            // 方向键上、下
            return (_that.isMax && isMax && keyCode === 38) || (_that.isMin && isMin && keyCode === 40);
        },
        /**
         * 转换数字
         * @param {Number} num 需要转换的内容
         * @returns {Number}
         */
        _toNumber(num) {
            let res = parseFloat(num);
            return isNaN(res) ? null : res;
        },
        /**
         * 加法计算
         * @param {Boolean} isSub 是否是减法
         */
        _addSub(isSub) {
            const _that = this;
            let arg1 = (_that.myValue || 0) + '';
            let arg2 = (parseFloat((_that.step || 1) + '') || 1) + '';
            const _arg1Arr = arg1.split('.');
            const _arg2Arr = arg2.split('.');
            const _r1 = ((_arg1Arr[1] || '') + '').length;
            const _r2 = ((_arg2Arr[1] || '') + '').length;
            const _decimal = Math.max(_r1, _r2);
            const _m = Math.pow(10, _decimal);
            if (isSub) {
                arg2 = 0 - arg2;
            }
            _that._setValue(((arg1 * _m + arg2 * _m) / _m).toFixed(_decimal));
        },
        /**
         * 当失去焦点
         * @param {Event} evt 事件对象
         */
        _onBlur (evt) {
            const _that = this;
            let _myValue = _that.myValue;
            _that._setValue(_myValue || (_myValue + '' === '0' ? _myValue : (_that.myMinNum || 0)));
            _that.$emit('blur', evt);
        },
        /**
         * 设置值
         * @param {Number} val 设置的值
         */
        _setValue (val) {
            const _that = this;
            let _val = ((val || '') + '');
            let _arr = _val.match(/\./g) || [];
            if (_arr.length === 1 && /\.$/.test(_val)) {
                return;
            }
            let _res = _that._resetStatus(val);
            if (typeof _res.val === 'number' && val != _res.val) {
                _that.$emit('error', {type: val > _res.val ? 1 : -1});
            }
            _that.isMin = _res.isMin;
            _that.isMax = _res.isMax;
            _that.myValue = _res.val;
        },
        /**
         * 重置状态
         * @param {Number} val 当前的value值
         * @returns {Object} 返回过滤后的值
         */
        _resetStatus (val) {
            const _that = this;
            let _myMinNum = _that.myMinNum;
            let _myMaxNum = _that.myMaxNum;
            let _hasMin = (typeof _myMinNum === 'number');
            let _hasMax = (typeof _myMaxNum === 'number');
            if (val !== '') {
                val = (!_hasMin || (_hasMin && _myMinNum < 0)) && val === '-' ? val : _that._toNumber(val);
                if (typeof val === 'number') {
                    val = _hasMin ? Math.max(val, _myMinNum) : val;
                    val = _hasMax ? Math.min(val, _myMaxNum) : val;
                }
            }
            return {
                isMin: _hasMin && (val === _myMinNum),
                isMax: _hasMax && (val === _myMaxNum),
                val: val
            };
        }
    }
};
</script>

<style lang="scss">
@import '../../../_assets/style/_iconFont.scss';
@import '../../../_assets/style/_var.scss';
@import '../../../_assets/style/_mixin.scss';
.nus_number {
    box-sizing: border-box;
    display: inline-block;
    user-select: none;
    height: 30px;
    line-height: 30px;
    border: {
        width: 1px;
        style: solid;
        color: $nunumber-br-color;
    };
    .nu_number-box {
        height: 100%;
    }
    .nu_number-disable {
        color: $nunumber-btn-diable-color;
    }
    .nu_number-btn,.nu_number-input{
        padding: 0;
        height: 100%;
        text-align: center;
        vertical-align: top;
        display: inline-block;
        border-color: inherit;
        position: relative;
    }
    .nu_number-btn {
        width: 1.75em;
    }
    .nu_number-input {
        width: 45px;
        margin: 0;
        border: {
            width: 1px;
            style: solid;
            color: inherit;
            top: none;
            bottom: none;
        };
        .nu_input{
            padding: 0;
            text-align: center;
            display: block;
        }
    }
}
</style>
