<template>
  <v-app>
    <v-layout>
      <DemoNotificationNavigationDrawer
        v-model="notificationDropdown.modal"
        :notifications="notifications"
      />
      <ViewerNavigationDrawer @close="m_closeDialog = true" />
      <ViewerAppBar @close="m_closeDialog = true" />
      <ViewerActionBar />
      <v-main id="main-panel">
        <LoadingSpinner v-if="scanLoading" />
        <ViewerMain
          v-show="!scanLoading"
          @loaded="load"
        />
        <DataOverlayModal />
        <CloseViewerModal v-model:modal="m_closeDialog" />
        <ViewerIntro
          v-model="introActive"
          @start="tourActive = true"
        />
        <ViewerTour v-model="tourActive" />
        <DownloadSnack />
      </v-main>
    </v-layout>
  </v-app>
</template>

<script setup lang="ts">
import { storeToRefs } from 'pinia';
import { nextTick, onMounted, ref, watch } from 'vue';
import {
  DataOverlaysActions,
  FileManagementActions,
  FrontEndInterfaces,
  GraphicType,
  McadActions,
  NotificationsActions,
  ScanStateActions,
} from '@3cr/types-ts';
import {
  scanState,
  setInitialScanStateFromPayload,
  setScanStateFromPayload,
  transactionStarted,
} from '@/models/scanState';
import { useViewer3cr } from '@/composables/useViewer3cr';
import { useScanMovement } from '@/composables/useScanMovement';
import { useScanSliders } from '@/composables/useScanSliders';
import { LoadSessionState } from '@3cr/types-ts/types/LoadSessionState';
import { useDataOverlayStore } from '@/stores/data-overlay.store';
import { useMcadStore } from '@/stores/mcad.store';
import { mockDemoViewerStlDecimator } from '@/components/demo/mockDemoViewerStlDecimator';
import { useViewerStore } from '@/stores/viewer.store';
import { useIntroStore } from '@/stores/intro.store';
import { useDrawerStore } from '@/stores/drawer.store';
import { useDemoStore } from '@/stores/demo.store';
import { DEMO_BUCKET_URL } from '@/constants';
import { useNotificationHandler } from '@/composables/useNotificationHandler';
import { DemoType, ViewerOptions, ViewerPayload } from '@3cr/viewer-types-ts';
import { useDemoNotifications } from '../demo/demo-notifications';
import DownloadSnack from '@/components/modal/snackbars/DownloadSnack.vue';
interface Props {
  payload?: ViewerPayload;
  options?: ViewerOptions;
}

const props = withDefaults(defineProps<Props>(), {
  options: () => ({}),
});

useScanMovement();
useScanSliders();
const { handler } = useNotificationHandler();
const { notifications } = useDemoNotifications();
const viewer3cr = useViewer3cr();
const dataOverlayStore = useDataOverlayStore();
const mcadStore = useMcadStore();
const { activeDrawer } = storeToRefs(useDrawerStore());
const { dontShowAgain } = storeToRefs(useIntroStore());
const { setIsDemo } = useDemoStore();
const { isDemo, demoOptions, demoType, notificationDropdown } =
  storeToRefs(useDemoStore());
const {
  options: opts,
  enableMouse,
  enableKeyboard,
  defaultLayout2x2,
} = storeToRefs(useViewerStore());

const scanLoading = ref<boolean>(true);
const m_closeDialog = ref<boolean>(false);
const introActive = ref<boolean>(false);
const tourActive = ref<boolean>(false);

watch(
  props,
  (props) => {
    if (props.payload) {
      setIsDemo(props.payload);
      opts.value = isDemo.value ? demoOptions.value : props.options;
    }
  },
  { immediate: true },
);

/* v8 ignore start -- @preserve */
onMounted(() => {
  viewer3cr.addInterfaceHandler(
    FrontEndInterfaces.notifications,
    async (message: string, action: string) => {
      await handler(action as NotificationsActions, message);
    },
  );

  viewer3cr.addActionHandler(
    FileManagementActions.fm02,
    async (message: string) => {
      enableMouse.value = true;
      enableKeyboard.value = true;
      setInitialScanStateFromPayload(message);
      if (opts.value.onScanLoaded) {
        await opts.value.onScanLoaded(scanState.value);
      }
      await nextTick();

      transactionStarted.value = false;
      scanLoading.value = false;
      activeDrawer.value = 'display';
      await loadDemoData();

      // setup navigation cube
      switch (demoType.value) {
        case DemoType.Licence:
          await viewer3cr.setNavCubeGraphics(GraphicType.LETTER);
          break;
        case DemoType.Patient:
          await viewer3cr.setNavCubeGraphics(GraphicType.BODY_SYMBOL);
          break;
      }

      // setup layouts
      const msg = { Version: '0.0.0', PositionData: defaultLayout2x2.value };
      await viewer3cr.customLayout({ message: msg });

      if (!dontShowAgain.value) {
        introActive.value = true;
      }
    },
  );

  viewer3cr.addActionHandler(
    FileManagementActions.fm09,
    async (_1: string, returnChannel: string, returnTo: string) => {
      if (opts.value.onResolveKeys) {
        const keys = JSON.parse(returnChannel) as string[];
        const urls = await opts.value.onResolveKeys(keys);
        await viewer3cr.loadMcadObjects({
          message: undefined,
          returnChannel: urls,
          returnTo,
        });
      } else {
        throw new Error(
          'onResolveKeys has not been defined in the viewer options',
        );
      }
    },
  );

  viewer3cr.addActionHandler(ScanStateActions.ss01, async (message: string) => {
    await setScanStateFromPayload(message);
  });

  viewer3cr.addActionHandler(ScanStateActions.ss02, (message: string) => {
    dataOverlayStore.setDataOverlayState(message);
  });

  viewer3cr.addActionHandler(ScanStateActions.ss03, (message: string) => {
    mcadStore.setMcadState(message);
  });

  viewer3cr.addActionHandler(DataOverlaysActions.do01, (message: string) => {
    dataOverlayStore.setInitialDataOverlayState(message);
  });

  viewer3cr.addActionHandler(DataOverlaysActions.do02, (message: string) => {
    dataOverlayStore.setDataOverlayEvent(message);
  });

  viewer3cr.addActionHandler(DataOverlaysActions.do07, (message: string) => {
    dataOverlayStore.setDataOverlayEvent(message);
  });

  viewer3cr.addActionHandler('mu_17', (message: string) => {
    dataOverlayStore.setDataOverlayEvent(message);
  });

  viewer3cr.addActionHandler('mu_18', (message: string) => {
    dataOverlayStore.setDataOverlayEvent(message);
  });

  viewer3cr.addActionHandler(McadActions.mc01, (message: string) => {
    mcadStore.setInitialMcadState(message);
  });

  viewer3cr.addActionHandler(McadActions.mc02, (message: string) => {
    mcadStore.setMcadEvent(message);
  });
});
/* v8 ignore stop -- @preserve */

/* v8 ignore start -- @preserve */
async function loadSession(url: string): Promise<void> {
  const message: LoadSessionState = { Version: '0.0.0', Url: url };
  if (url.includes('3crs')) {
    await viewer3cr.loadScanSession({ message });
  } else if (url.includes('3crds')) {
    await viewer3cr.setDataOverlaySession({ message });
  } else if (url.includes('3crms')) {
    await viewer3cr.loadMcadObjects({ message });
  } else {
    throw new Error('Invalid URL type');
  }
}
/* v8 ignore stop -- @preserve */

async function load(): Promise<void> {
  scanLoading.value = true;
  await viewer3cr.loadScan({ message: props.payload });
}

/* v8 ignore start -- @preserve */
async function loadDemoData(): Promise<void> {
  if (isDemo.value) {
    mockDemoViewerStlDecimator();
    const annotations: LoadSessionState = {
      Version: '0.0.0',
      Url: `${DEMO_BUCKET_URL}/state/annotations.3crds`,
    };
    await viewer3cr.addDataOverlaySession({ message: annotations });
    const measurements: LoadSessionState = {
      Version: '0.0.0',
      Url: `${DEMO_BUCKET_URL}/state/measurements.3crds`,
    };
    await viewer3cr.addDataOverlaySession({ message: measurements });
  }
}
/* v8 ignore stop -- @preserve */

defineExpose({ loadSession, load, m_closeDialog, introActive, tourActive });
</script>
