<template>
  <section class="sv-input-wrapper" :class="{'is-textarea': type === 'textarea'}">
    <template v-if="type === 'textarea'">
      <textarea
        class="sv-textarea"
        :placeholder="placeholder"
        v-model="inputValue"
        :maxlength="maxlength"
        :rows="textareaRows"
        ref="textareaRef"></textarea>
    </template>
    <template v-else>
      <div class="sv-input-left" v-if="showInputLeft">
        <div class="sv-input-icon left-icon" v-if="hasIcon && iconPosition === 'left'">
          <slot name="icon">
            <sv-icon :icon="inputLeftIcon" v-if="inputLeftIcon"></sv-icon>
          </slot>
        </div>
      </div>
      <input
        v-if="type !== 'search'"
        class="sv-input"
        :class="inputClass"
        :inputType="type"
        :placeholder="placeholder"
        :maxlength="maxlength"
        v-model="inputValue"
        ref="svInputRef"
        @input="handleInput"
        @click="handleClick"
        :readonly="inputReadonly"
        :disabled="disabled"/>
      <form v-else action="javascript: void(0);" class="sv-adapter-form">
        <input
          class="sv-input"
          :class="inputClass"
          :inputType="type"
          :placeholder="placeholder"
          :maxlength="maxlength"
          v-model="inputValue"
          ref="svInputRef"
          @input="handleInput"
          @click="handleClick"
          @keypress.enter="handleSearch"
          :readonly="inputReadonly"
          :disabled="disabled"
          autocomplete="off"
          autocorrect="off"/>
      </form>
      <div class="sv-input-right" v-if="showInputRight">
        <div class="sv-input-icon right-icon" v-if="(hasIcon && iconPosition === 'right') || (inputType === 'password' && toggleVisible) || (clearable && inputValue)">
          <slot name="icon">
            <sv-icon icon="clear" v-if="clearable && inputValue" @click="handleClearClick"></sv-icon>
            <sv-icon :icon="{'password-hide': !passwordVisible, 'password-show': passwordVisible}" v-if="inputType === 'password' && toggleVisible" @click="togglePasswordVisible"></sv-icon>
            <sv-icon :icon="inputRightIcon" v-if="inputRightIcon"></sv-icon>
          </slot>
        </div>
        <div class="sv-input-unit" v-if="unit">
          <div class="unit-text">{{unit}}</div>
        </div>
      </div>
    </template>
  </section>
</template>

<script type="text/ecmascript-6">
  export default {
    name: 'svInput',
    data () {
      return {
        inputValue: this.value,
        inputType: this.type,
        inputReadonly: this.readonly,
        passwordVisible: false,
        textareaRows: this.rows
      }
    },
    props: {
      value: [String, Number],
      icon: {
        type: String,
        default: ''
      },
      iconPosition: {
        type: String,
        default () {
          return 'left'
        }
      },
      size: {
        type: String,
        default: ''
      },
      type: {
        type: String,
        default: 'text'
      },
      placeholder: {
        type: String,
        default: ''
      },
      readonly: {
        type: Boolean,
        default: false
      },
      disabled: {
        type: Boolean,
        default: false
      },
      toggleVisible: {
        type: Boolean,
        default: true
      },
      maxlength: {
        type: [String, Number]
      },
      unit: {
        type: String,
        default: ''
      },
      clearable: {
        type: Boolean,
        default: false
      },
      negative: {
        type: Boolean,
        default: true
      },
      positive: {
        type: Boolean,
        default: true
      },
      rows: {
        type: [String, Number],
        default: 1,
        validator (val) {
          let intValue = window.parseInt(val)
          if (Number.isNaN(intValue)) {
            console.error('rows应为大于0的整数或能转换为数字的字符串')
            return false
          } else if (intValue <= 0) {
            console.error('rows应为大于0的整数')
            return false
          }
          return true
        }
      },
      autosize: {
        type: [Boolean, Object],
        default: false
      }
    },
    watch: {
      inputValue (val) {
        this.setInputValue(val)
      },
      value (val) {
        this.setInputValue(val)
      }
    },
    computed: {
      inputClass () {
        let inputClass = ''
        if (this.size) {
          inputClass += `sv-input-${this.size}`
        }
        if (this.disabled) {
          inputClass += ` disabled`
        }
        return inputClass
      },
      inputLeftIcon () {
        if (this.iconPosition === 'left') {
          return this.icon ? `${this.icon}` : ''
        }
        return ''
      },
      inputRightIcon () {
        if (this.iconPosition === 'right') {
          return this.icon ? `${this.icon}` : ''
        }
        return ''
      },
      hasIcon () {
        if (this.icon || this.$slots.icon) {
          return true
        }
        return false
      },
      showInputLeft () {
        return this.hasIcon
      },
      showInputRight () {
        if ((this.icon && this.iconPosition === 'right') ||
          (this.inputType === 'password' && this.toggleVisible) ||
          (this.clearable && this.inputValue) ||
          this.unit) {
          return true
        }
        return false
      }
    },
    methods: {
      handleInput (event) {
        let value = event.target.value
        this.setInputValue(value)
      },
      setInputValue (value) {
        value = value + '' // 将数字类型转换为字符串类型
        // html5默认的type="number"时maxlength属性不生效，于是在此自己实现maxlength功能
        if (value.length > this.maxlength) {
          value = value.substr(0, this.maxlength)
        }

        if (this.type === 'integer') {
          let newValue = value
          value = value.replace(/\D+/g, '')
          if (this.negative && newValue.startsWith('-')) {
            value = '-' + value
          }
        }

        if (this.type === 'number') {
          if (typeof this.enableNegative === 'string') {
            if (this.enableNegative === '' || this.enableNegative === 'true') {
              this._enableNegative = true
            } else {
              this._enableNegative = false
            }
          }

          if (typeof this.enableNegative === 'boolean') {
            this._enableNegative = this.enableNegative
          }

          if (this._enableNegative) {
            let startValue = ''
            if (value.startsWith('-')) {
              startValue = '-'
              if (value.charAt(1) === '.') {
                startValue = '-'
              }
            }

            value = value.replace(/[^\d.]/g, '')

            if (startValue === '-') {
              if (value === '.') {
                value = ''
              }
            }
            value = startValue + value
          } else {
            value = value.replace(/[^\d.]/g, '')
          }

          let values = value.split('.')

          if (values.length === 2) {
            if (!values[0]) {
              value = ''
            } else {
              let newValue = ''
              newValue = values[0] + '.' + (values[1] ? values[1].substring(0, 2) : '')
              value = newValue
            }
          }

          if (values.length > 2) {
            values.pop()
            let newValue = ''
            for (let i = 0; i < values.length; i++) {
              newValue += i === values.length - 1 ? values[i] : values[i] + '.'
            }
            value = newValue
          }
        }

        if (this.type === 'hour') {
          value = value.replace(/\D+/g, '')
          if (value.charAt(0) === '0') {
            value = value.charAt(0)
          }
          if (window.parseInt(value) > 23) {
            value = value.substr(0, value.length - 1)
          }
        }
        this.inputValue = value
        this.$emit('input', value)
      },
      setInputType (type) {
        if (type === 'integer') {
          type = 'number'
        }
        this.$nextTick(() => {
          this.$refs.svInputRef.setAttribute('type', type)
        })
      },
      togglePasswordVisible () {
        this.passwordVisible = !this.passwordVisible
        this.setInputType(this.passwordVisible ? 'text' : 'password')
      },
      handleClick (value) {
        if (this.readonly) {
          this.forbidKeyboardPop()
        }
        this.$emit('click', value)
      },
      handleSearch (event) {
        event.stopPropagation()
        event.preventDefault()
        this.$emit('search', event)
      },
      /**
       * 禁止键盘弹出
       */
      forbidKeyboardPop () {
        document.activeElement.blur()
      },
      handleClearClick () {
        this.inputValue = ''
        this.$emit('input', '')
        this.$emit('clear')
      },
      autosizeTextarea () {
        if (typeof this.autosize === 'object') {
          if (this.autosize.minRows) {
            this.textareaRows = this.autosize.minRows
          }
        }
        this.$nextTick(() => {
          let $textarea = this.$refs.textareaRef
          let lineHeight = $textarea.clientHeight / this.textareaRows
          $textarea.style.height = $textarea.scrollHeight + 'px'
          $textarea.addEventListener('input', () => {
            if (typeof this.autosize === 'object' && this.autosize.maxRows) {
              if ($textarea.scrollHeight < lineHeight * this.autosize.maxRows) {
                $textarea.style.height = $textarea.scrollHeight + 'px'
              } else {
                $textarea.style.height = lineHeight * this.autosize.maxRows + 'px'
              }
            } else {
              $textarea.style.height = $textarea.scrollHeight + 'px'
            }
          }, false)
        })
      }
    },
    created () {
      if (this.type === 'textarea') {
        if (this.autosize) {
          this.autosizeTextarea()
        }
      } else {
        this.setInputType(this.inputType)
      }

      if (this.disabled) {
        this.inputReadonly = true
      }
    }
  }
</script>

<style lang="scss" rel="stylesheet/scss">
  @import "../../styles/base";
  .sv-input-wrapper{
    display: flex;
    justify-content: space-between;
    align-items: center;
    width:100%;
    height: pxToRem(80);
    overflow: hidden;
    border: pxToRem(1) solid $input-border-color;
    border-radius: pxToRem(4);
    font-size: pxToRem($input-font-size);
    &.is-textarea{
      height: auto;
      min-height: pxToRem(80);
      padding: pxToRem(20);
      .sv-textarea{
        width: 100%;
        overflow: auto;
        font-size: pxToRem($input-font-size);
        color: $input-text-color;
        margin:0;
        padding:0;
        outline: none;
        border: none;
        resize: none;
        line-height: 1;
        &::-webkit-scrollbar{
          display: none;
        }
        &::-webkit-input-placeholder{
          font-size: pxToRem($input-font-size);
          color: $input-placeholder-color;
          vertical-align: middle;
        }
      }
    }
    .sv-input-icon{
      display: flex;
      font-size: pxToRem($input-font-size);
      color:#bbb;
    }
    .sv-adapter-form{
      flex: 1;
      width: 100%;
      height: 100%;
      input[type="search"]::-webkit-search-cancel-button{
        display: none;
      }
      -webkit-appearance: none;
    }
    .sv-input{
      flex: 1;
      color:#333;
      border: none;
      width: 100%;
      height: 100%;
      padding: pxToRem(0 20);
      line-height: 1;
      &::-webkit-input-placeholder{
        font-size: pxToRem(30);
        color:#ccc;
      }
      &.disabled{
        background: #f5f7fa;
        color:#c0c4cc;
        &::-webkit-input-placeholder{
          font-size: pxToRem($input-font-size);
          color: $input-placeholder-color;
        }
      }
    }
    .sv-input-left, .sv-input-right{
      display: flex;
      align-items: center;
      height: 100%;
    }
    .sv-input-left{
      .sv-input-icon{
        margin-left: pxToRem(20);
      }
    }
    .sv-input-right{
      .sv-input-icon{
        margin-right: pxToRem(20);
      }
      .sv-input-unit{
        display: flex;
        align-items: center;
        height: 100%;
        padding:pxToRem(0 14);
        box-sizing: border-box;
        border-left: 1px solid #bfcbd9;
        background-color: #fbfdff;
        color: #97a8be;
        font-style: normal;
        font-size: pxToRem(24);
        .unit-text{
          max-width: pxToRem(100);
          white-space: nowrap;
          overflow: hidden;
          text-overflow: ellipsis;
        }
      }
    }
  }

</style>
