<template>
  <v-navigation-drawer :border="drawer ? 1 : 0" color="background" permanent rail rail-width="80">
    <template #prepend>
      <div class="d-flex justify-center">
        <v-hover>
          <template #default="{ isHovering, props: hover }">
            <v-tooltip open-delay="1000" location="right">
              <template #activator="{ props: tooltip }">
                <v-btn
                  data-testid="nav-btn"
                  v-bind="mergeProps(hover, tooltip)"
                  :icon="true"
                  variant="text"
                  color="minsk_500"
                  size="large"
                  @click="close"
                >
                  <v-img
                    v-if="!isHovering"
                    src="@/assets/logos/3dicom/colour/colour_single.svg"
                    width="40"
                    height="40"
                  />
                  <v-icon v-else icon="west" />
                </v-btn>
              </template>
              <span>{{ t('labels.backToPortal') }}</span>
            </v-tooltip>
          </template>
        </v-hover>
      </div>
    </template>
    <v-list
      data-testid="nav-list"
      :selected="[activeDrawer]"
      class="px-1"
      density="compact"
      nav
      @update:selected="activeDrawer = $event[0]"
    >
      <template v-for="item in items" :key="item.value">
        <template v-if="item.visible">
          <v-tooltip open-delay="1000" location="right">
            <template #activator="{ props }">
              <v-list-item
                v-bind="props"
                class="mx-auto py-0"
                width="42px"
                :data-testid="`listitem-${item.value}`"
                min-height="30px"
                color="primary"
                :prepend-icon="item.icon"
                :value="item.value"
                @click="item.listItemProps.onClick"
              />
              <div class="text-center text-xs-semibold mb-4" :data-testid="`title-${item.value}`">{{ item.title }}</div>
            </template>
            <span>{{ item.tooltip }}</span>
            <span class="pl-2">{{ item.tooltipShortcut }}</span>
          </v-tooltip>
        </template>
      </template>
    </v-list>
    <template #append>
      <div class="d-flex flex-column align-center">
        <v-list density="compact" nav>
          <HelpMenu />
        </v-list>
        <span class="pb-2 text-xs-regular">{{ version }}</span>
      </div>
    </template>
  </v-navigation-drawer>
  <v-navigation-drawer
    :border="0"
    color="background"
    :model-value="drawer"
    :width="width"
    :elevation="canDrag ? 4 : 0"
    style="min-width: 264px; max-width: 512px"
    permanent
    class="resizable-drawer"
  >
    <v-fade-transition hide-on-leave>
      <template v-for="item in items" :key="item.value">
        <template v-if="activeDrawer == item.value">
          <Component v-bind="item.props" :is="item.component" />
        </template>
      </template>
    </v-fade-transition>
  </v-navigation-drawer>
</template>

<script setup lang="ts">
import { ComponentInstance, computed, inject, mergeProps, onMounted, ref, watch } from 'vue';
import DisplayPanel from '@/components/navigation/display/DisplayPanel.vue';
import AnnotationPanel from '@/components/navigation/annotation/AnnotationPanel.vue';
import MeasurementPanel from '@/components/navigation/measurement/MeasurementPanel.vue';
import McadPanel from '@/components/navigation/mcad/McadPanel.vue';
import { useDataOverlayStore } from '@/stores/data-overlay.store';
import { useMcadStore } from '@/stores/mcad.store';
import { useViewerStore } from '@/stores/viewer.store';
import { storeToRefs } from 'pinia';
import { defaultHotkeys, defineHotkeys, Hotkeys, HotkeyScope, resetScope } from '@/functions/HotkeyScope';
import interact from 'interactjs';
import { useI18n } from 'vue-i18n';
import { useDrawerStore } from '@/stores/drawer.store';
import { SHORTCUT_TEXT, translateTooltipShortcut } from '@/functions/translateTooltipShortcut';
import { VERSION } from '@/plugins/version';

onMounted(() => {
  defaultHotkeys({
    [Hotkeys.ALT_D]: async () => {
      activeDrawer.value = 'display';
    },
    [Hotkeys.ALT_H]: async () => {
      activeDrawer.value = 'home';
    },
    [Hotkeys.ALT_A]: async () => {
      activeDrawer.value = 'annotation';
    },
    [Hotkeys.ALT_M]: async () => {
      activeDrawer.value = 'measure';
    },
    [Hotkeys.ALT_E]: async () => {
      activeDrawer.value = 'design';
    }
  });
});

interface NavigationDrawerItem {
  icon: string;
  title: string;
  tooltip: string;
  tooltipShortcut: string;
  value: string;
  visible: boolean;
  component: ComponentInstance<any>;
  props: Record<string, any>;
  listItemProps: Record<string, any>;
}

type Emits = {
  close: [void];
};

const emit = defineEmits<Emits>();

const { t } = useI18n();
const { annotations, measurements } = storeToRefs(useDataOverlayStore());
const { activeDrawer } = storeToRefs(useDrawerStore());
const { mcads } = storeToRefs(useMcadStore());
const { options } = storeToRefs(useViewerStore());

const version = inject(VERSION)!;

const width = ref<number>(264);

const drawer = computed(() => {
  return !!activeDrawer.value && !!items.value.find((x) => activeDrawer.value === x.value)?.component;
});

const items = computed<NavigationDrawerItem[]>(() => [
  {
    value: 'home',
    icon: options.value.home?.icon ?? 'home',
    tooltip: options.value.home?.title ?? t('labels.home'),
    tooltipShortcut: translateTooltipShortcut(SHORTCUT_TEXT.altH),
    title: options.value.home?.title ?? t('labels.home'),
    visible: true,
    component: undefined,
    props: {},
    listItemProps: {}
  },
  {
    value: 'display',
    icon: options.value.display?.icon ?? 'visibility',
    tooltip: options.value.display?.title ?? t('labels.display'),
    tooltipShortcut: translateTooltipShortcut(SHORTCUT_TEXT.altD),
    title: options.value.display?.title ?? t('labels.display'),
    visible: options.value.display?.visible ?? true,
    component: DisplayPanel,
    props: {},
    listItemProps: {}
  },
  {
    value: 'annotation',
    icon: options.value.annotations?.icon ?? 'stylus_note',
    tooltip: options.value.annotations?.title ?? t('labels.annotation'),
    tooltipShortcut: translateTooltipShortcut(SHORTCUT_TEXT.altA),
    title: options.value.annotations?.title ?? t('labels.annotation'),
    visible: options.value.annotations?.visible ?? true,
    component: AnnotationPanel,
    props: {
      items: annotations.value
    },
    listItemProps: {}
  },
  {
    value: 'measure',
    icon: options.value.measure?.icon ?? 'design_services',
    tooltip: options.value.measure?.title ?? t('labels.measure'),
    tooltipShortcut: translateTooltipShortcut(SHORTCUT_TEXT.altM),
    title: options.value.measure?.title ?? t('labels.measure'),
    visible: options.value.measure?.visible ?? true,
    component: MeasurementPanel,
    props: {
      items: measurements.value
    },
    listItemProps: {}
  },
  {
    value: 'design',
    icon: options.value.design?.icon ?? 'view_in_ar',
    tooltip: options.value.design?.title ?? t('labels.design'),
    tooltipShortcut: translateTooltipShortcut(SHORTCUT_TEXT.altE),
    title: options.value.design?.title ?? t('labels.design'),
    visible: options.value.design?.visible ?? true,
    component: McadPanel,
    listItemProps: {},
    props: {
      items: mcads.value
    }
  }
]);

const canDrag = computed(() => activeDrawer.value === 'mcad');

watch(activeDrawer, () => {
  width.value = 264;
  interact('.resizable-drawer').resizable({
    edges: { top: false, left: false, bottom: false, right: canDrag.value },
    listeners: {
      /* v8 ignore next 3 */
      move: function (event) {
        width.value = Math.min(Math.max(event.rect.width, 264), 512);
      }
    }
  });
});

// Some issue with coverage not recognising the watch for drawer.
/* v8 ignore start */
watch(drawer, (isOpen: boolean) => {
  if (isOpen) {
    defineHotkeys(HotkeyScope.PRIMARY, {
      [Hotkeys.ALT_D]: async () => {
        activeDrawer.value = 'display';
      },
      [Hotkeys.ALT_H]: async () => {
        activeDrawer.value = 'home';
      },
      [Hotkeys.ALT_A]: async () => {
        activeDrawer.value = 'annotations';
      },
      [Hotkeys.ALT_M]: async () => {
        activeDrawer.value = 'measure';
      },
      [Hotkeys.ALT_E]: async () => {
        activeDrawer.value = 'design';
      }
    });
  } else {
    resetScope(HotkeyScope.PRIMARY);
  }
});
/* v8 ignore start */

async function close(): Promise<void> {
  if (options.value.onExit) {
    await options.value.onExit();
  }
  emit('close');
}

defineExpose({
  drawer
});
</script>
