<template>
  <div :class="cls">
    <slot />
  </div>
</template>

<script>

export default {
  name: 'ElSteps',
  props: {
    /**
     * @zh 步骤条的类型
     * @en The type of the steps
     * @values 'default', 'arrow', 'dot', 'navigation'
     */
    type: {
      type: String,
      default: 'default',
    },
    /**
     * @zh 步骤条的显示方向
     * @en The direction of the steps
     * @values 'horizontal', 'vertical'
     */
    direction: {
      type: String,
      default: 'horizontal',
    },
    /**
     * @zh 标签描述文字放置的位置
     * @en The location where the label description is placed.
     * @values 'horizontal', 'vertical'
     */
    labelPlacement: {
      type: String,
      default: 'vertical',
    },
    /**
     * @zh 当前步骤数
     * @en Number of current step
     * @vModel
     */
    current: {
      type: Number,
      default: undefined,
    },
    /**
     * @zh 默认的步骤数（非受控状态）
     * @en The default number of step (uncontrolled state)
     */
    defaultCurrent: {
      type: Number,
      default: 1,
    },
    /**
     * @zh 当前步骤的状态
     * @en The status of the current step
     * @values 'wait', 'process', 'finish', 'error'
     */
    status: {
      type: String,
      default: 'process',
    },
    /**
     * @zh 是否使用无连接线样式
     * @en Whether to use the connectionless style
     */
    lineLess: {
      type: Boolean,
      default: false,
    },
    /**
     * @zh 是否使用小型步骤条
     * @en Whether to use a small step bar
     */
    small: {
      type: Boolean,
      default: false,
    },
    /**
     * @zh 是否可以点击切换
     * @en Whether you can click to switch
     */
    changeable: {
      type: Boolean,
      default: false,
    },
  },
  computed: {
    computedCurrent() {
      return this.current || this._current;
    },
    directions() {
      return ['navigation', 'arrow'].includes(this.type)
        ? 'horizontal'
        : this.direction
    },
    labelPlacements() {
      if (this.type === 'dot') {
        return this.direction === 'vertical' ? 'horizontal' : 'vertical';
      }
      if (this.type === 'navigation') {
        return 'horizontal';
      }
      if (this.direction === 'vertical') {
        return 'horizontal'
      }
      return this.labelPlacement;
    },
    errorSteps() {
      return Array.from(this.stepMap.values())
        .filter((item) => item.status === 'error')
        .map((item) => item.step)
    },
    cls() {
      return [
        this.prefixCls,
        `${this.prefixCls}-${this.direction}`,
        `${this.prefixCls}-label-${this.labelPlacements}`,
        `${this.prefixCls}-mode-${this.type}`,
        {
          [`${this.prefixCls}-changeable`]: this.changeable,
          [`${this.prefixCls}-size-small`]: this.small && this.type !== 'dot',
          [`${this.prefixCls}-line-less`]: this.lineLess,
        },
      ]
    }
  },
  data() {
    return {
      stepMap: new Map(),
      _current: '',
      prefixCls: 'el-steps'
    }
  },
  provide() {
    return {
      type: this.type,
      direction: this.directions,
      labelPlacement: this.labelPlacements,
      lineLess: this.lineLess,
      current: this.computedCurrent,
      errorSteps: this.errorSteps,
      getStatus: this.getStatus,
      addItem: this.addItem,
      removeItem: this.removeItem,
      onClick: this.handleClick,
      parentCls: this.prefixCls
    }
  },
  methods: {
    getStatus(step) {
      if (step < this.computedCurrent) {
        return 'finish';
      }
      if (step > this.computedCurrent) {
        return 'wait';
      }
      return this.status;
    },
    handleClick(step, e) {
      if (this.changeable) {
        this._current = step;
        this.$emit('update:current', step);
        this.$emit('change', step, e);
      }
    },
    addItem(step, data) {
      this.stepMap.set(step, data);
    },
    removeItem(step) {
      this.stepMap.delete(step);
    }
  }
}
</script>

<style scoped>

</style>
