<template>
  <div class="n-input" :class="getBorderClass({border, disabled, isFocus: active || isFocus})">
    <input :is="!isTextarea ? 'input' : 'textarea'" :value="nValue"
           :style="isTextarea ? {resize} : null"
           :class="getValueClass({size, disabled, ellipsis: !isTextarea, rightIcon: iconProps, uppercase})"
           v-bind="{name, placeholder, disabled, rows: nRows || rows, maxlength, readonly, autocomplete, ...$attrs}"
           v-on="{ ...$listeners, compositionstart, compositionend, input: onUserInput}"
           @focus="onFocus" @blur="onBlur" @keyup.enter="onEnter" />
    <n-resize v-if="nRows" :class="getValueClass({size, disabled, ellipsis: !isTextarea, rightIcon: iconProps, uppercase})"
              class="fake-rows" @update="onFakeUpdate">{{fakeValue}}</n-resize>
    <n-icon v-if="iconProps" class="n-form-icon" v-bind="iconProps" @mousedown.native="onIconMousedown" @click="onIconClick"></n-icon>
  </div>
</template>
<script>
import NIcon from '@uif/next/lib/components/icon'
import NResize from '@uif/next/lib/components/resize'
import {prop, isNumber, isFormValue} from '@uif/next/lib/utils/tools'
import vModel from '_common/vModel'
import {getBorderClass, getValueClass} from '_common/formUtils'
import {isDynamicRows, getDynamicFakeValue, formatUserInputValue, formatUserValue, getElementRows} from '_common/inputUtils'

export default {
  inheritAttrs: false,
  name: 'n-input',
  mixins: [vModel],
  components: {
    NIcon,
    NResize
  },
  props: {
    // 表单名称
    name: prop.string(),
    // 表单值
    value: prop.stringNumber(),
    // input 类型
    type: prop.inArray(['text', 'textarea', 'password', 'number'], 'text'),
    // input 大小
    size: prop.inArray(['small', 'middle', 'large'], 'middle'),
    // input 边框形状
    border: prop.inArray(['none', 'line', 'rect'], 'rect'),
    // textarea resize
    resize: prop.inArray(['none', 'vertical'], 'none'), // 'both', 'horizontal',
    // 激活状态
    active: prop.boolean(),
    // 禁用
    disabled: prop.boolean(),
    // 只读
    readonly: prop.boolean(),
    // 高度
    rows: {
      validator: (value) => isDynamicRows(value) || isNumber(value),
      default: 3 // 'auto' 'rows'
    },
    // 数值输入
    number: {
      type: [Number, Boolean],
      default: false
    },
    // 负数
    negative: prop.boolean(),
    // 可清空
    clearable: prop.boolean(),
    // 附加icon
    suffixIcon: prop.string(),
    // 附加icon类型
    suffixIconScene: prop.string('gray'),
    // 输入提示
    placeholder: prop.string(),
    // 最长长度
    maxlength: prop.number(null),
    // 自动填充
    autocomplete: prop.string('off'),
    // 去首位空
    trim: prop.boolean(true),
    // 自动大写
    uppercase: prop.boolean()
  },
  data () {
    return {
      getBorderClass,
      getValueClass,
      nValue: this.value,
      isOnComposition: false,
      isFocus: false,
      // 动态高度值
      nRows: this.type === 'textarea' && isDynamicRows(this.rows) ? 1 : 0
    }
  },
  computed: {
    isTextarea ({type}) {
      return type === 'textarea'
    },
    fakeValue ({rows, nValue}) {
      return isDynamicRows(rows) ? getDynamicFakeValue(nValue) : ''
    },
    // 右侧icon
    iconProps ({clearable, disabled, nValue, suffixIcon, suffixIconScene}) {
      if (clearable && !disabled && isFormValue(nValue)) {
        return {type: 'circle-delete', scene: 'light', isRemove: true}
      } else if (suffixIcon) {
        return {type: suffixIcon, scene: suffixIconScene, disabled}
      }
      return null
    }
  },
  methods: {
    setValue (value) {
      if (this.nValue !== value) {
        this.nValue = value
        this.$emit('u-update', this.nValue)
      }
    },
    // 用户输入事件
    onUserInput (event) {
      if (!this.isOnComposition) {
        const {uppercase, number, negative} = this
        const value = formatUserInputValue({value: event.target.value, uppercase, number, negative})
        this.setValue(value)
        if (event.target.value !== value) {
          event.target.value = value
        }
      }
    },
    // 获取焦点
    onFocus () {
      this.isFocus = true
      this.onAutoRowsUpdate()
      this.backup = this.nValue
      this.$emit('u-focus', this)
    },
    // 失去焦点
    onBlur (event) {
      if (this.isOnClear) {
        this.isOnClear = event.target.value = ''
      }
      const value = formatUserValue({value: event.target.value, uppercase: this.uppercase, number: this.number, needTrim: this.trim})
      this.setValue(value)
      this.isFocus = false
      this.onAutoRowsUpdate()
      this.$emit('u-blur', this)
      if (this.nValue !== this.backup) {
        this.$emit('u-change', this.nValue)
      }
    },
    // 回车事件
    onEnter (event) {
      if (this.type !== 'textarea') {
        const value = formatUserValue({value: event.target.value, uppercase: this.uppercase, number: this.number, needTrim: this.trim})
        this.setValue(value)
        this.$emit('u-enter', this.nValue)
      }
    },
    // 拼音输入 start
    compositionstart () {
      this.isOnComposition = true
    },
    // 拼音输入 end
    compositionend (event) {
      this.isOnComposition = false
      this.onUserInput(event)
    },
    // 更新自动高度
    onFakeUpdate (rect, element) {
      this.nRows = (this.rows === 'auto' && !this.isFocus) ? 1 : getElementRows(element)
    },
    // 自动折叠
    onAutoRowsUpdate () {
      if (this.nRows && this.rows === 'auto') {
        if (this.isFocus) {
          this.nRows = this.backRows || this.nRows
        } else {
          this.backRows = this.nRows
          this.nRows = 1
        }
      }
    },
    // icon mousedown
    onIconMousedown () {
      if (this.iconProps.isRemove) {
        this.isOnClear = true
      }
    },
    // icon 点击
    onIconClick (event) {
      // 清除按钮
      if (this.iconProps.isRemove && this.isOnClear) {
        this.isOnClear = this.nValue = ''
        this.$emit('u-update', this.nValue)
        this.$emit('u-change', this.nValue)
      } else if (!this.iconProps.isRemove) {
        // 后置icon点击
        this.$emit('icon-click', event)
      }
    }
  }
}
</script>
