<template>
  <FormItem ref="item"
            class="x-form-item"
            :style="styles"
            :prop="prop"
            v-bind="$attrs"
            v-on="$listeners">
    <slot></slot>
    <slot slot="label" name="label"></slot>
    <template v-slot:error="{error}">
      <slot name="error" :error="error">
        <Tooltip v-if="status" v-bind="tooltipOptions" :content="error">
          <XIcon :style="iconStyle" :class="iconClass" :size="iconSize" :name="invalidIcon"></XIcon>
        </Tooltip>
      </slot>
    </template>
  </FormItem>
</template>

<script>
/**
 * 表单项目组件
 * @module XFormItem
 */
import { FormItem, Tooltip } from 'element-ui';
import { XIcon } from '@newpearl/ui';
import { proxyMethods } from '../../utils';

/**
 * 插槽
 * @member slots
 * @property {string} default Form Item 的内容
 * @property {string} label 标签文本的内容
 * @property {string} error 作用域插槽，自定义表单校验信息的显示方式，参数为 { error }
 */
export default {
  name: 'XFormItem',
  inheritAttrs: false,
  inject: {
    xForm: {
      default: null
    }
  },
  components: {
    FormItem,
    XIcon,
    Tooltip
  },
  /**
   * 参数属性
   * @member props
   * @property {boolean} [status=true] 开启图标显示校验信息
   * @property {string} [invalidIcon=el-icon-warning] 验证不通过时显示的图标
   * @property {number} [iconSize=16] 图标尺寸
   * @property {number} [iconRight] 图标左侧偏移量
   * @property {boolean|object} [tooltip=true] tooltip配置, 对象方式即是el-tooltip的参数
   * @property {number} [width] 表单项宽度
   * @property {string} [prop] 表单字段名称
   * @property {string} [suffixSelector=.el-input__suffix] 后缀选择器
   */
  props: {
    // 开启状态图标显示验证信息
    status: {
      type: Boolean,
      default: true
    },
    // 无效图标
    invalidIcon: {
      type: String,
      default: 'el-icon-warning'
    },
    // 图标尺寸
    iconSize: {
      type: Number,
      default: 16
    },
    iconRight: {
      type: Number
    },
    // tooltip配置
    tooltip: {
      type: [Boolean, Object],
      default: true
    },
    width: String,
    // 表单字段名
    prop: {
      type: String
    },
    // 输入框后缀选择器
    suffixSelector: {
      type: String,
      default: '.el-input__suffix'
    }

  },
  data() {
    return {
      labelWidth: 0,
      suffixWidth: 0
    };
  },
  computed: {
    tooltipOptions() {
      return {
        placement: 'top',
        ...this.tooltip,
        disabled: !this.tooltip,
        popperClass: 'x-form-item__tooltip'
      };
    },
    iconClass() {
      return {
        'x-form-item__icon': true,
        'is-tooltip-disabled': this.tooltipOptions.disabled
      };
    },
    styles() {
      return {
        width: this.width
      };
    },
    iconStyle() {
      if (this.iconRight) {
        return {
          right: `${this.iconRight}px`
        };
      }
      if (this.suffixWidth) {
        return {
          right: `${this.suffixWidth}px`
        };
      }
      return null;
    }
  },
  methods: {
    /**
     * 对该表单项进行重置，将其值重置为初始值并移除校验结果
     * @method resetField
     */

    /**
     * 移除该表单项的校验结果
     * @method clearValidate
     */
    ...proxyMethods(['resetField', 'clearValidate'], 'item'),
    updateIconPosition() {
      const suffix = this.$el.querySelector(this.suffixSelector);
      if (!suffix) return;
      const rect = suffix.getBoundingClientRect();
      this.suffixWidth = rect.width;
    }
  },
  mounted() {
    const vnode = this.$slots.default ? this.$slots.default[0] : null;
    this.updateIconPosition();
    if (vnode && vnode.componentInstance && this.xForm) {
      const instance = vnode.componentInstance;
      this.focusHandler = e => {
        // 确保在blur之后触发focus
        setTimeout(() => {
          this.xForm.focusComponent = instance;
          this.$emit('focus', instance, e);
          this.xForm.$emit('focus', instance, e, this);
        }, 50);
      };
      this.blurHandler = e => {
        this.xForm.focusComponent = null;
        this.$emit('blur', instance, e);
        this.xForm.$emit('blur', instance, e, this);
      };
      instance.$on('focus', this.focusHandler);
      instance.$on('blur', this.blurHandler);
      this.slotComponent = instance;
      if (this.prop) {
        this.xForm.fieldInstances[this.prop] = instance;
      }
    }
  },
  beforeDestroy() {
    if (this.xForm) {
      if (this.prop) {
        delete this.xForm.fieldInstances[this.prop];
      }
      if (this.slotComponent) {
        this.slotComponent.$off();
      }
    }
  }
};
</script>
