<template>
  <div
    class="hn-step-node"
    :style="style"
    :class="[
      isLast && !space && !isCenter && 'is-flex',
      isCenter && 'is-center'
     ]">
    <!-- header -->
    <div
      class="hn-step-node__header"
      :class="['is-' + currentStatus]">
      <div
        class="hn-step-node__header__description"
        :class="['is-' + currentStatus]">
        <slot name="headerDescription">{{ headerDescription }}</slot>
      </div>
      <div
        class="hn-step-node__header__title"
        :class="['is-' + currentStatus]">
        <slot name="headerTitle">{{ headerTitle }}</slot>
      </div>
    </div>
    <!-- icon & line -->
    <div
      class="hn-step-node__head"
      :class="[
        `is-${currentStatus}`,
      ]">
      <div
        class="hn-step-node__line"
        :style="stepLineStyle"
      >
        <i class="hn-step-node__line-inner" :style="lineStyle"></i>
      </div>

      <div class="hn-step-node__icon" :class="`is-${icon ? 'icon' : 'text'}`">
        <slot
          v-if="currentStatus !== 'finish' && currentStatus !== 'error'"
          name="icon">
          <i v-if="icon" class="hn-step-node__icon-inner" :class="[icon]"></i>
          <div class="hn-step-node__icon-inner" v-if="!icon">{{ index + 1 }}</div>
        </slot>
        <i
          v-else
          :class="['hn-icon-' + (currentStatus === 'finish' ? 'check' : 'close')]"
          class="hn-step-node__icon-inner is-status"
        >
        </i>
      </div>
    </div>
    <!-- title & description -->
    <div class="hn-step-node__main">
      <div
        class="hn-step-node__title"
        :class="['is-' + currentStatus]">
        <slot name="title">{{ title }}</slot>
      </div>
      <div
        class="hn-step-node__description"
        :class="['is-' + currentStatus]">
        <slot name="description">{{ description }}</slot>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'HnStepNode',

  props: {
    headerTitle: String,
    headerDescription: String,
    title: String,
    icon: String,
    description: String,
    status: String
  },

  data() {
    return {
      lineStyle: {},
      internalStatus: ''
    };
  },

  created() {
    if (!this.$isServer) return;
    const activeIndex = this.$parent.active;
    this.updateStatus(activeIndex);
  },

  beforeDestroy() {
    const steps = this.$parent.steps;
    const index = steps.indexOf(this.$vnode);
    if (index >= 0) {
      steps.splice(index, 1);
    }
  },

  computed: {
    index() {
      return this.$parent.steps.indexOf(this.$vnode);
    },
    currentStatus() {
      return this.status || this.internalStatus;
    },
    prevStatus() {
      const prevStep = this.$parent.$children[this.index - 1];
      return prevStep ? prevStep.currentStatus : 'wait';
    },
    isCenter() {
      return this.$parent.alignCenter;
    },
    isLast() {
      const steps = this.$parent.steps;
      return steps[steps.length - 1] === this.$vnode;
    },
    stepsCount() {
      return this.$parent.steps.length;
    },
    space() {
      return this.$parent.space ;
    },
    style: function() {
      const style = {};
      const parent = this.$parent;
      const len = parent.steps.length;

      const space = (typeof this.space === 'number'
        ? this.space + 'px'
        : this.space
          ? this.space
          : 100 / (len - (this.isCenter ? 0 : 1)) + '%');
      style.flexBasis = space;
      if (this.isLast) {
        style.maxWidth = 100 / this.stepsCount + '%';
      }

      return style;
    },
    stepLineStyle() {
      const { isCenter, $parent } = this;
      const stepLineStyle = {};
      if (isCenter) {
        stepLineStyle.left = `calc(50% + ${$parent.lineOffset})`;
        stepLineStyle.right = `calc(-50% + ${$parent.lineOffset})`;
      }
      return stepLineStyle;
    }
  },

  methods: {
    updateStatus(val) {
      const prevChild = this.$parent.$children[this.index - 1];

      if (val > this.index) {
        this.internalStatus = this.$parent.finishStatus;
      } else if (val === this.index && this.prevStatus !== 'error') {
        this.internalStatus = this.$parent.processStatus;
      } else {
        this.internalStatus = 'wait';
      }

      if (prevChild) prevChild.calcProgress(this.internalStatus);
    },

    calcProgress(status) {
      let step = 100;
      const style = {};

      style.transitionDelay = 150 * this.index + 'ms';
      if (status === this.$parent.processStatus) {
        step = this.currentStatus !== 'error' ? 0 : 0;
      } else if (status === 'wait') {
        step = 0;
        style.transitionDelay = (-150 * this.index) + 'ms';
      }

      style.borderWidth = step ? '1px' : 0;
      style.width = step + '%';

      this.lineStyle = style;
    }
  },

  mounted() {
    this.$watch('$parent.active', this.updateStatus, { immediate: true });
    this.$watch('$parent.processStatus', () => {
      const activeIndex = this.$parent.active;
      this.updateStatus(activeIndex);
    }, { immediate: true });
  }
};
</script>
