<template>
  <div
    :class="{
      'full-width': !showSummary,
      'no-header': !showHeader
    }"
    :style="{
      height: wizardHeight
    }"
    class="vc-wizard"
  >
    <div class="vc-wizard-steps">
      <div class="vc-wizard-steps-content">
        <div
          v-show="showHeader"
          class="steps-header"
        >
          <div class="px-5">
            <slot
              v-if="$slots['header-nav']"
              name="header-nav"
            />
            <span
              v-else
              class="text-sm font-medium "
            >
              {{ $tVU.t('wizard.step.of', { current: activeIndex + 1, length: steps.length }) }}
            </span>
          </div>
          <div class="px-5">
            <slot name="header-info" />
          </div>
        </div>
        <div class="steps-content">
          <div class="vc-stepper__items relative">
            <VcWizardTransition
              :direction="direction"
            >
              <template
                v-for="(step, index) in steps"
                :key="`step-${index}`"
              >
                <div
                  v-show="index === activeIndex"
                  v-bind="step.attrs"
                  class="vc-stepper__content"
                >
                  <slot
                    :name="step.step"
                    :step="step"
                    :index="index"
                  />
                </div>
              </template>
            </VcWizardTransition>
          </div>
        </div>
        <VcWizardNavigation
          :show-prev-btn="!!activeIndex"
          :show-next-btn="!isFinalStep"
          :show-final-btn="isFinalStep"
          :show-final-add-slot="isFinalAddSlot"
          :loading="dataLoading"
          :disabled-next-btn="!canNext"
          @on-cancel="onCancel"
          @on-prev="onPrev"
          @on-next="onNext"
          @on-final="onFinal"
        >
          <template
            v-if="isFinalAddSlot"
            #additional-actions
          >
            <slot name="final-actions" />
          </template>
          <template
            v-if="$slots['extra-actions']"
            #extra-actions
          >
            <slot name="extra-actions" />
          </template>
          <template
            v-if="$slots.navigation"
            #navigation
          >
            <slot name="navigation" />
          </template>
        </VcWizardNavigation>
      </div>
    </div>
    <VcWizardSummary
      v-if="showSummary"
      :steps="steps"
      :active-index="activeStep"
      :visited="maxVisited"
      :content="summary"
      @update-step="goToStep"
    />
  </div>
</template>

<script lang="ts">
import { defineComponent, PropType } from 'vue'
import Transition from './baseTransition'
import VcWizardSummary from '@/components/VcWizard/VcWizardSummary.vue'
import VcWizardTransition from '@/components/VcWizard/VcWizardTransition.vue'
import VcWizardNavigation from '@/components/VcWizard/VcWizardNavigation.vue'
import { VcWizardStepType, VcWizardSummaryType } from './VcWizard.types'
import { convertToUnit } from '@/utils/helpers'

export default defineComponent({
  name: 'VcWizard',
  components: { VcWizardNavigation, VcWizardTransition, VcWizardSummary },
  mixins: [Transition],
  props: {
    activeStep: {
      type: [Number, String],
      default: 0
    },
    steps: {
      type: Array as PropType<VcWizardStepType[]>,
      default: () => []
    },
    showHeader: {
      type: Boolean,
      default: true
    },
    showSummary: {
      type: Boolean,
      default: true
    },
    dataLoading: {
      type: Boolean,
      default: false
    },
    summary: {
      type: Object as PropType<VcWizardSummaryType>,
      default: () => ({})
    },
    height: {
      type: [String, Number],
      default: '100%'
    },
    canNext: {
      type: Boolean,
      default: true
    }
  },
  emits: ['update-step', 'cancel', 'final'],
  data: () => ({
    activeIndex: 0,
    maxVisited: 0,
    direction: 'right'
  }),
  computed: {
    isFinalStep (): boolean {
      return this.activeIndex >= this.steps?.length - 1
    },
    isStartStep (): boolean {
      return this.activeIndex === 0
    },
    isFinalAddSlot (): boolean {
      return !!(this.isFinalStep && this.$slots['final-actions'])
    },
    wizardHeight (): string | undefined {
      return convertToUnit(this.height)
    }
  },
  watch: {
    activeIndex (newV, oldVal) {
      if (newV > oldVal) {
        this.direction = 'right'
      } else {
        this.direction = 'left'
      }
      this.setMaxVisitedStep(newV)
    },
    activeStep () {
      this.setActiveIndex()
    }
  },
  mounted () {
    this.setActiveIndex()
  },
  methods: {
    setMaxVisitedStep (val: number): void {
      if (val >= 0 && val > this.maxVisited) {
        this.maxVisited = val
      }
    },
    onNext (): void {
      if (!this.isFinalStep) {
        this.goToStep(this.activeIndex + 1)
      }
    },
    onPrev (): void {
      if (this.activeIndex > 0) {
        this.goToStep(this.activeIndex - 1)
      }
    },
    goToStep (index: number): void {
      this.$emit('update-step', index, {
        isVisited: index <= this.maxVisited
      })
    },
    onCancel (): void {
      this.$emit('cancel')
    },
    onFinal (): void {
      this.$emit('final')
    },
    setActiveIndex (): void {
      if (!isNaN(Number(this.activeStep))) {
        this.activeIndex = +this.activeStep
      } else {
        const index = this.steps.findIndex((i: VcWizardStepType) => i?.step === this.activeStep)
        this.activeIndex = index >= 0 ? index : 0
      }
    }
  }
})
</script>

<style lang="scss">
$summaryWidthXl: 425px;
$summaryWidthLg: 380px;
$stepsHeader: 60px;
$stepsNavigation: 80px;
$stepsHeightDiv: $stepsHeader + $stepsNavigation;

.vc-wizard {
  --vc-wizard-summary-width: #{$summaryWidthXl};
  --vc-wizard-header: #{$stepsHeader};
  --vc-wizard-navigation: #{$stepsNavigation};
  &.no-header {
    --vc-wizard-header: 0px;
  }
  @apply
  w-full
  relative
  shadow-card
  rounded-md
  flex
  justify-between
  overflow-hidden;

  &-steps {
    @apply h-full w-full overflow-hidden;
    max-width: calc(100% - var(--vc-wizard-summary-width));
  }
  &.full-width {
    .vc-wizard-steps {
      max-width: 100%;
    }
  }

  &-steps-content {
    @apply w-full h-full relative flex flex-col overflow-hidden;

    .steps-header {
      @apply w-full hidden lg:flex justify-between items-center py-3 px-4 lg:px-8 xxl:px-15;
      flex: 0 0 var(--vc-wizard-header);
    }
    .steps-content {
      @apply bg-white overflow-hidden;
      flex: 1 0 auto;
      max-height: calc(100% - var(--vc-wizard-header) - var(--vc-wizard-navigation));
    }

    .vc-stepper__items {
      @apply w-full h-full bg-white relative box-border flex;
      .vc-stepper__content {
        @apply top-0 p-6 w-full h-full overflow-y-auto;
        flex: 1 0 auto;
      }
    }
  }

  @media only screen and (max-width: 1680px) {
    --vc-wizard-summary-width: #{$summaryWidthLg}
  }
  @media only screen and (max-width: 1264px) {
    --vc-wizard-summary-width: 100%;
    --vc-wizard-header: 0px;
    flex-direction: column;
    &-steps {
      max-width: 100%;
      order: 2;
    }
  }
}
</style>
