<template>
  <div class="x-number-input">
    <div v-if="type === 'edit'" :class="{ 'el-input-number is-controls-right': showOpt }">
      <span
        v-if="showOpt && !disabled"
        role="button"
        class="el-input-number__decrease"
        :class="{ 'is-disabled': disabledDownBtn() }"
        @click="downNum"
        ><i class="el-icon-arrow-down"></i
      ></span>
      <span
        v-if="showOpt && !disabled"
        role="button"
        class="el-input-number__increase"
        :class="{ 'is-disabled': disabledUpBtn() }"
        @click="upNum"
        ><i class="el-icon-arrow-up"></i
      ></span>
      <el-input
        :value="data"
        :placeholder="placeholder"
        :disabled="disabled"
        :maxlength="15"
        :readonly="readonly"
        @input="dataChangeEvent($event)"
        @blur="formatNumber($event)"
        @focus="deleteZero($event)"
        @change="blurOrEnter"
        @keydown.up.native.prevent="upNum"
        @keydown.down.native.prevent="downNum"
      >
        <template v-slot:suffix>
          <slot name="suffix"></slot>
        </template>
        <template v-slot:prefix>
          <slot name="prefix"></slot>
        </template>
      </el-input>
    </div>
    <x-ellipsis v-if="type === 'read'" mode="origin" :label="data"></x-ellipsis>
  </div>
</template>
<script>
import MoneyUtil from '../../utils/money.util'
export default {
  name: 'XNumberInput',
  model: {
    prop: 'configValue',
    event: 'change'
  },
  props: {
    type: {
      type: String,
      default: 'edit'
    },
    showOpt: {
      type: Boolean,
      default: true
    },
    decimalNum: {
      type: Number
    },
    placeholder: {
      type: String,
      default: '请输入'
    },
    configValue: {
      type: [Number, String],
      require: true
    },
    moneyDisplayStyle: {
      type: String,
      default: 'NUMBER'
    },
    maxValue: {
      type: Number,
      default: null
    },
    minValue: {
      type: Number,
      default: null
    },
    disabled: {
      type: Boolean,
      default: false
    },
    readonly: {
      type: Boolean,
      default: false
    },
    step: {
      type: Number,
      default: 1
    }
  },
  data() {
    return {
      data: '',
      flag: false,
      upBtnDisable: false,
      downBtnDisable: false
    }
  },
  watch: {
    configValue: {
      handler(newValue, oldValue) {
        if (!this.flag) {
          if (newValue) {
            if (Object.prototype.toString.call(newValue) === `[object String]`) {
              this.$emit('change', parseFloat(newValue))
            }
          }
          if (newValue === undefined || newValue === null) {
            this.data = ''
          } else {
            this.data = this.dealDecimalNum(parseFloat(newValue))
          }
        }
      },
      immediate: true
    },
    maxValue: {
      handler(newVal, oldVal) {
        if (newVal !== undefined && newVal !== null) {
          if (this.configValue !== undefined && this.configValue !== null) {
            if (parseFloat(this.configValue) > newVal) {
              this.dealValue(this.maxValue)
              this.disabledUpBtn()
            }
          }
        }
      },
      immediate: true
    },
    minValue: {
      handler(newVal, oldVal) {
        if (newVal !== undefined && newVal !== null) {
          if (this.configValue !== undefined && this.configValue !== null) {
            if (parseFloat(this.configValue) < newVal) {
              this.dealValue(this.minValue)
              this.disabledDownBtn()
            }
          }
        }
      },
      immediate: true
    },
    decimalNum: {
      handler(newVal, oldVal) {
        if (newVal !== undefined && newVal !== null) {
          this.dealValue(this.configValue)
        }
      },
      immediate: true
    }
  },
  methods: {
    dataChangeEvent(e) {
      const value = e
      const reg = /^-?(0|[1-9][0-9]*)(\.[0-9]*)?$/ // 数字正则
      if (
        (!isNaN(value) && reg.test(value)) ||
        value === '' ||
        value === '-' ||
        value.startsWith('.') ||
        value.startsWith('-.')
      ) {
        if (value === '' || value === '-' || value === '-.' || value === '.') {
          this.flag = true
          this.$emit('change', null)
          this.data = value
        } else if (value.startsWith('.')) {
          this.flag = true
          this.$emit('change', parseFloat('0' + value))
          this.data = value
        } else if (value.startsWith('-.')) {
          this.flag = true
          this.$emit('change', parseFloat('-0' + value.substring(1)))
          this.data = value
        } else {
          this.flag = true
          this.$emit('change', parseFloat(value))
          this.data = value
          // this.configValue = 0
        }
      }
      this.$emit('input', this.data)
    },
    formatNumber(e) {
      if (!this.readonly) {
        const value = this.configValue
        if (
          this.minValue !== undefined &&
          this.minValue !== null &&
          parseFloat(value) < this.minValue
        ) {
          this.dealValue(this.minValue)
        } else if (
          this.maxValue !== undefined &&
          this.maxValue !== null &&
          parseFloat(value) > this.maxValue
        ) {
          this.dealValue(this.maxValue)
        } else {
          this.dealValue(value)
        }
      }
      this.flag = false
      this.$emit('blur', e)
    },
    deleteZero(e) {
      if (!this.readonly) {
        if (this.configValue !== undefined && this.configValue !== null) {
          this.data = this.configValue.toString()
        } else {
          this.data = ''
        }
      }
      this.$emit('focus', e)
    },
    dealValue(value) {
      if (value !== undefined && value !== null) {
        const num = parseFloat(value)
        if (num === 0) {
          this.$emit('change', 0)
          this.data = this.dealDecimalNum(num)
        } else {
          this.$emit('change', parseFloat(this.dealDecimalNum(num)))
          this.data = this.dealDecimalNum(num)
        }
      } else {
        this.data = ''
      }
    },
    dealDecimalNum(value) {
      let data = ''
      if (this.decimalNum !== undefined && this.decimalNum !== null) {
        const length = value.toString().split('.')[0].length
        // 修复由于小数点位数造成的精度问题
        if (length + this.decimalNum >= 15) {
          if (length > 14) {
            data = value.toString()
          } else {
            data = (
              Math.floor(value * Math.pow(10, 14 - length)) / Math.pow(10, 14 - length)
            ).toFixed(14 - length)
          }
        } else {
          data = (
            Math.floor(value * Math.pow(10, this.decimalNum)) / Math.pow(10, this.decimalNum)
          ).toFixed(this.decimalNum)
        }
      } else {
        data = value.toString()
      }
      return data
    },
    upNum() {
      if (!this.readonly) {
        if (this.configValue === undefined || this.configValue === null) {
          if (this.minValue !== undefined && this.minValue !== null) {
            this.dealValue(this.minValue)
          } else if (this.maxValue !== undefined && this.maxValue !== null) {
            this.dealValue(this.maxValue)
          } else {
            this.dealValue(0)
          }
        } else {
          if (this.maxValue !== undefined && this.maxValue !== null) {
            if (this.configValue < this.maxValue) {
              if (Math.floor(this.configValue) !== this.configValue) {
                this.dealValue(
                  (this.configValue + +this.step).toFixed(
                    this.configValue.toString().split('.')[1].length
                  )
                )
              } else {
                this.dealValue(this.configValue + +this.step)
              }
            } else {
            }
          } else {
            if (Math.floor(this.configValue) !== this.configValue) {
              this.dealValue(
                (this.configValue + +this.step).toFixed(
                  this.configValue.toString().split('.')[1].length
                )
              )
            } else {
              this.dealValue(this.configValue + +this.step)
            }
          }
        }
      }
    },
    downNum() {
      if (!this.readonly) {
        if (this.configValue === undefined || this.configValue === null) {
          if (this.minValue !== undefined && this.minValue !== null) {
            this.dealValue(this.minValue)
          } else if (this.maxValue !== undefined && this.maxValue !== null) {
            this.dealValue(this.maxValue)
          } else {
            this.dealValue(0)
          }
        } else {
          if (this.minValue !== undefined && this.minValue !== null) {
            if (this.configValue > this.minValue) {
              if (Math.floor(this.configValue) !== this.configValue) {
                this.dealValue(
                  (this.configValue - +this.step).toFixed(
                    this.configValue.toString().split('.')[1].length
                  )
                )
              } else {
                this.dealValue(this.configValue - +this.step)
              }
            } else {
            }
          } else {
            if (Math.floor(this.configValue) !== this.configValue) {
              this.dealValue(
                (this.configValue - +this.step).toFixed(
                  this.configValue.toString().split('.')[1].length
                )
              )
            } else {
              this.dealValue(this.configValue - +this.step)
            }
          }
        }
      }
    },
    disabledUpBtn() {
      if (this.maxValue !== undefined && this.maxValue !== null) {
        return this.configValue >= this.maxValue
      } else {
        return false
      }
    },
    disabledDownBtn() {
      if (this.minValue !== undefined && this.minValue !== null) {
        return this.configValue <= this.minValue
      } else {
        return false
      }
    },
    blurOrEnter(e) {
      this.$emit('blurOrEnter', +e)
    }
  }
}
</script>
