<script setup lang="ts" generic="T extends Step">
import { computed, defineProps, defineModel, withDefaults } from 'vue';
import MIcon from '../icon/MIcon.vue';

export type Step = {
  id: string | number;
  label: string;
  tooltip?: string;
  isValid?: boolean;
};

type StepperAccessibilityLabels = {
  stepperDescription: string;
  validatedLabel: string;
  currentLabel: string;
  disabledLabel: string;
};

const emit = defineEmits<{ clickOnStep: [value: T['id']] }>();
const modelValue = defineModel<T['id']>();
const props = withDefaults(
  defineProps<{
    steps: T[];
    accessibilityLabels?: StepperAccessibilityLabels;
    clickable?: boolean;
    compact?: boolean;
  }>(),
  {
    accessibilityLabels: () => ({
      stepperDescription: 'this is a stepper',
      validatedLabel: 'step validated',
      currentLabel: 'current step',
      disabledLabel: 'step disabled',
    }),
    clickable: false,
    compact: false,
  },
);

const currentIndex = computed(() =>
  props.steps.findIndex((step) => step.id === modelValue.value),
);

const classObject = computed(() => ({
  'mc-stepper--compact': !!props.compact,
  'mc-stepper--shrinked': props.steps.length > 3,
}));

const isStepValidated = (step: T, index: number) => {
  if (step.isValid !== undefined) {
    return step.isValid;
  }

  return index < currentIndex.value;
};

const isCurrentStep = (step: T) => {
  return modelValue.value === step.id;
};

const stepDescription = (step: T, index: number) => {
  return `#${index + 1} ${step.label}, ${stepStateLabel(step, index)}`;
};

const stepStateLabel = (step: T, index: number) => {
  return isStepValidated(step, index)
    ? props.accessibilityLabels.validatedLabel
    : isCurrentStep(step)
      ? props.accessibilityLabels.currentLabel
      : props.accessibilityLabels.disabledLabel;
};

const onClickOnStep = (step: T) => {
  emit('clickOnStep', step.id);
};
</script>

<template>
  <nav
    class="mc-stepper"
    :class="classObject"
    :aria-label="props.accessibilityLabels.stepperDescription"
  >
    <ol class="mc-stepper__list">
      <li
        v-for="(step, index) in steps"
        :key="`mc-stepper__item-${index}`"
        class="mc-stepper__item"
        :class="{
          'mc-stepper__item--validated': isStepValidated(step, index),
          'mc-stepper__item--current': step.id === modelValue,
        }"
        :aria-current="isCurrentStep(step) ? 'step' : false"
        :aria-label="stepDescription(step, index)"
        :title="step.tooltip"
        :style="`--steps: ${steps.length}; --current: ${index + 1};`"
      >
        <a
          v-if="clickable"
          href="#"
          class="mc-stepper__link"
          @click.prevent="onClickOnStep(step)"
        >
          <div class="mc-stepper__indicator" aria-hidden="true">
            <span v-if="step.id === modelValue">{{ index + 1 }}</span>
            <MIcon
              v-else-if="isStepValidated(step, index)"
              name="NotificationAvailable16"
              class="mc-stepper__icon"
            />
          </div>
          <div class="mc-stepper__detail">
            <span class="mc-stepper__title">
              {{ index + 1 }} / {{ steps.length }}
            </span>
            <span class="mc-stepper__label">{{ step.label }}</span>
          </div>
        </a>
        <template v-else>
          <div
            class="mc-stepper__indicator"
            aria-hidden="true"
            style="cursor: pointer"
          >
            <span v-if="isCurrentStep(step)">{{ index + 1 }}</span>
            <MIcon
              v-else-if="isStepValidated(step, index)"
              name="NotificationAvailable16"
              class="mc-stepper__icon"
            />
          </div>
          <div class="mc-stepper__detail">
            <span class="mc-stepper__title">
              {{ index + 1 }} / {{ steps.length }}
            </span>
            <span class="mc-stepper__label">{{ step.label }}</span>
          </div>
        </template>
      </li>
    </ol>
  </nav>
</template>

<style lang="scss" scoped>
@import 'settings-tools/all-settings';
@import 'components/c.stepper';
</style>
