<template>
  <div @click="focusNewTag()" v-bind:class="{'read-only': readOnly}" class="vue-input-tag-wrapper">
    <span v-for="(tag, index) in tagArr" v-bind:key="index" class="input-tag">
      <span>{{ tag }}</span>
      <a v-if="!readOnly" @click.prevent.stop="remove(index)" class="remove"></a>
    </span>
    <span class="new-tag-wrap">
      <input v-if="!readOnly" v-bind:placeholder="placeholder" :minlength="minChars" :maxlength="maxChars" type="text" v-model="newTag"
        @input="handleInput"
        @blur="handleBlur"
        @keydown.delete.stop="removeLastTag()" @keydown.enter.188.prevent.stop="addNew(newTag)"
        @keydown.tab="handleTabDown"
        class="new-tag" />
      <transition name="el-zoom-in-top">
        <div v-if="validateResult === false" class="el-form-item__error">
          {{validateMessage}}
        </div>
      </transition>
    </span>
  </div>

</template>

<script>
/*eslint-disable*/
const validators = {
  email: new RegExp(
    /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
  ),
  url: new RegExp(/^(https?|ftp|rmtp|mms):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+)(:(\d+))?\/?/i),
  text: new RegExp(/^[a-zA-Z]+$/),
  digits: new RegExp(/^[\d() \.\:\-\+#]+$/),
  isodate: new RegExp(/^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/)
}
/* eslint-enable */

export default {
  name: 'InputTag',

  props: {
    tags: {
      type: [String, Array],
      default: ''
    },
    'minChars': { // tag最小字符长度
      type: Number,
      default: 2
    },
    'maxChars': { // tag最大字符长度
      type: Number,
      default: 10
    },
    'limit': { // 最大个数
      type: Number
    },
    placeholder: {
      type: String,
      default: ''
    },
    onChange: {
      type: Function
    },
    onAddError: {
      type: Function,
      default: function () {}
    },
    readOnly: {
      type: Boolean,
      default: false
    },
    validate: {
      type: String | Object,
      default: ''
    },
    errorMsg: {
      type: String,
      default: '校验不通过'
    }
  },

  data() {
    return {
      newTag: '',
      tagValues: '',
      validateResult: true,
      validateMessage: ''
    }
  },
  computed: {
    tagArr() {
      if (typeof this.tagValues === 'string') {
        return this.tagValues === '' ? [] : this.tagValues.split(',')
      } else if (_.isArray(this.tagValues)) {
        return this.tagValues
      }
      return []
    }
  },
  watch: {
    tags(val) {
      if (typeof val === 'string' && val !== this.tagValues) {
        this.tagValues = val
      } else if (_.isArray(val) && _.isEqual(this.tagValues, val) === false) {
        this.tagValues = val
      } else {
        this.tagValues = ''
      }
    }
  },
  methods: {
    focusNewTag() {
      if (this.readOnly) {
        return
      }
      this.$el.querySelector('.new-tag').focus()
    },
    handleTabDown(e) {
      if (this.newTag !== '') {
        e.stopPropagation()
        e.preventDefault()
        this.addNew(this.newTag)
      }
    },
    handleBlur() {
      if (this.newTag !== '') {
        this.addNew(this.newTag)
      }
    },
    addNew(tag) {
      if (tag && this.validateIfNeeded(tag)) {
        if (typeof this.tagValues === 'string') {
          if (this.tagValues === '') {
            this.tagValues = tag
          } else {
            this.tagValues = `${this.tagValues},${tag}`
          }
        } else {
          this.tagValues.push(tag)
        }
        this.tagChange()
        this.newTag = ''
      }
    },

    validateIfNeeded(tagValue) {
      let domEl = this.$el.querySelector('.new-tag')
      let errorMsg = ''
      let result = true
      if (this.tagArr.indexOf(tagValue) !== -1) {
        errorMsg = '关键词已经存在'
        result = false
      } else if (tagValue.length < this.minChars) {
        if (this.maxChars) {
          errorMsg = `长度限制为${this.minChars}-${this.maxChars}个字符`
        } else {
          errorMsg = `至少需要${this.minChars}个字符`
        }
        result = false
      } else if (this.maxChars && tagValue.length > this.maxChars) {
        errorMsg = `最多${this.maxChars}个字符`
        result = false
      } else if (this.limit && this.tagArr.length >= this.limit) {
        errorMsg = `关键词个数超出限制，最多可输入${this.limit}个关键词`
        result = false
      } else if (this.validate === '' || this.validate === undefined) {
        result = true
      } else if (typeof (this.validate) === 'string' && Object.keys(validators).indexOf(this.validate) > -1) {
        result = validators[this.validate].test(tagValue)
      } else if (typeof (this.validate) === 'object' && this.validate.test !== undefined) {
        result = this.validate.test(tagValue)
      }
      this.validateResult = result
      if (!result) {
        if (errorMsg === '') {
          errorMsg = this.errorMsg
        }
        this.validateMessage = errorMsg
        this.onAddError(domEl, errorMsg, tagValue)
        return result
      }
      return true
    },

    remove(index) {
      if (typeof this.tagValues === 'string') {
        let tempTagArr = this.tagValues.split(',')
        tempTagArr.splice(index, 1)
        this.tagValues = tempTagArr.join(',')
      } else {
        this.tagValues.splice(index, 1)
      }
      this.tagChange()
    },

    removeLastTag() {
      if (this.newTag) {
        return
      }
      if (typeof this.tagValues === 'string') {
        let tempTagArr = this.tagValues.split(',')
        tempTagArr.pop()
        this.tagValues = tempTagArr.join(',')
      } else {
        this.tagValues.pop()
      }
      this.tagChange()
    },
    handleInput() {
      this.validateResult = true
      this.validateMessage = ''
    },

    tagChange() {
      this.$emit('change', this.tagValues)
      if (this.onChange) {
        this.onChange(this.tagValues)
      }
    }
  }
}

</script>

<style>
  .vue-input-tag-wrapper {
    background-color: #fff;
    border: 1px solid #d8dce5;
    border-radius: 4px;
    padding-left: 4px;
    padding-top: 4px;
    cursor: text;
    text-align: left;
    line-height: 0;
    font-size: 0;
    -webkit-text-size-adjust: none;
    -webkit-appearance: textfield;
    -webkit-transition: border-color .2s cubic-bezier(.645, .045, .355, 1);
    transition: border-color .2s cubic-bezier(.645, .045, .355, 1);
  }

  .vue-input-tag-wrapper:hover {
    border-color: #b4bccc
  }

  .vue-input-tag-wrapper:focus {
    border-color: #28b06e;
    outline: 0
  }

  .vue-input-tag-wrapper .input-tag {
    background-color: #F9F9F9;
    border-radius: 2px;
    color: #666;
    display: inline-block;
    font-size: 14px;
    font-weight: 400;
    margin-bottom: 2px;
    margin-right: 4px;
    line-height: 20px;
    padding: 3px 5px;
  }

  .vue-input-tag-wrapper .input-tag .remove {
    cursor: pointer;
    font-weight: bold;
    color: #666;
  }

  .vue-input-tag-wrapper .input-tag .remove:hover {
    text-decoration: none;
  }

  .vue-input-tag-wrapper .input-tag .remove::before {
    content: " x";
  }

  .vue-input-tag-wrapper .new-tag-wrap {
    position: relative;
    display: inline-block
  }

  .vue-input-tag-wrapper .new-tag {
    background: transparent;
    border: 0;
    color: #777;
    font-size: 13px;
    font-weight: 400;
    margin-bottom: 6px;
    margin-top: 1px;
    outline: none;
    padding: 4px;
    padding-left: 0;
    line-height: 20px;
    width: 80px;
  }

  .vue-input-tag-wrapper.read-only {
    cursor: default;
  }

</style>
