<template>
  <div :class="classes">
    <input v-if="type !== 'textarea'" ref="input" :type="type" :number="number" :style="styles"
           class="input" :disabled="disabled" :name="name" v-model="currentValue"
           :placeholder="placeholder" :maxlength="maxlength" :readonly="readonly" :autocomplete="autocomplete"
           v-bind="$attrs" v-on="listeners" @focus="handleFocus" @blur="handleBlur" @input="handleInput"
           @compositionstart="handleCompositionstart" @compositionend="handleCompositionend">
    <textarea v-else ref="textarea" :style="styles" :rows="rows"
              class="input" :disabled="disabled" :name="name" v-model="currentValue"
              :placeholder="placeholder" :maxlength="maxlength" :readonly="readonly" :autocomplete="autocomplete"
              v-bind="$attrs" v-on="listeners" @focus="handleFocus" @blur="handleBlur" @input="handleInput"
              @compositionstart="handleCompositionstart" @compositionend="handleCompositionend"></textarea>
  </div>
</template>
<script>
import { oneOf } from '@uif/hq/src/utils/assist'
import { inputNumber, inputNumberValue, getNumberFromValue } from './format'
import {assign} from '@uif/hq/src/utils/object'

export default {
  inheritAttrs: false,
  name: 'u-input',
  props: {
    name: {
      type: String
    },
    value: {
      type: [String, Number],
      default: ''
    },
    type: {
      validator (value) {
        return oneOf(value, ['text', 'textarea', 'password', 'url', 'email', 'date', 'number', 'tel'])
      },
      default: 'text'
    },
    size: {
      validator (value) {
        return oneOf(value, ['small', 'default', 'large'])
      },
      default: 'default'
    },
    disabled: {
      type: Boolean,
      default: false
    },
    readonly: {
      type: Boolean,
      default: false
    },
    rows: {
      type: Number,
      default: 3
    },
    resize: {
      validator (value) {
        return oneOf(value, ['none', 'both', 'horizontal', 'vertical'])
      },
      default: 'none'
    },
    number: {
      type: [Number, Boolean],
      default: false
    },
    // 负数
    negative: {
      type: Boolean,
      default: false
    },
    ellipsis: {
      type: Boolean,
      default: true
    },
    border: {
      validator (value) {
        return oneOf(value, ['none', 'line', 'rect'])
      },
      default: 'rect'
    },
    placeholder: {
      type: String,
      default: ''
    },
    maxlength: {
      type: Number
    },
    autocomplete: {
      type: String,
      default: 'off'
    },
    focus: {
      type: Boolean,
      default: false
    },
    nativeStyle: {
      type: Object,
      default () {
        return {}
      }
    }
  },
  data () {
    return {
      currentValue: this.value,
      isFocus: false,
      isOnComposition: false
    }
  },
  computed: {
    classes () {
      return [
        'uif-input',
        'uif-input-size-' + this.size,
        'uif-input-border-' + this.border,
        {
          'available': !this.disabled,
          'disabled': this.disabled,
          'focus': this.isFocus || this.focus,
          'ellipsis': this.type !== 'textarea' && this.ellipsis
        }
      ]
    },
    styles () {
      const styles = assign({resize: this.resize}, this.nativeStyle)
      if (this.type !== 'textarea') {
        delete styles.resize
      }
      return styles
    },
    listeners () {
      const listeners = assign({}, this.$listeners)
      delete listeners.input
      return listeners
    }
  },
  watch: {
    value: {
      immediate: true,
      handler (val) {
        this.setValue(val)
      }
    }
  },
  mounted () {
  },
  methods: {
    // 设置 currentValue
    setValue (value) {
      if (value !== this.currentValue) {
        this.currentValue = value
      }
      if (this.value !== value) {
        this.$emit('input', value)
      }
    },
    // 用户输入事件
    handleInput (event) {
      if (this.isOnComposition) return
      let value = event.target.value
      if (inputNumber(this.number)) {
        value = getNumberFromValue(event.target.value, this.number, this.negative)
      }
      this.setValue(value)
      this.$emit('u-change', value)
    },
    // 失去焦点
    handleBlur (event) {
      this.isFocus = false
      if (inputNumber(this.number)) {
        this.setValue(inputNumberValue(event.target.value))
      }
    },
    handleFocus () {
      this.isFocus = true
    },
    handleCompositionstart () {
      this.isOnComposition = true
    },
    handleCompositionend (event) {
      this.isOnComposition = false
      this.handleInput(event)
    }
  }
}
</script>
