<template>
  <div
    :class="['scan-view', viewClass]"
    ref="container"
    @mouseenter="onMouseEnter"
    @mousedown="onMouseEnter"
    @mouseleave="onMouseLeave"
    @touchstart="onMouseEnter"
    @touchmove="onMouseEnter"
    @touchend="onMouseLeave"
    @dblclick="onDoubleClick"
  >
    <v-hover #default="{ isHovering, props }">
      <div v-bind="props" class="d-flex h-100 w-100">
        <div class="d-flex flex-column flex-fill overflow-hidden">
          <div class="pa-2">
            <span class="text-white">{{ name }}</span>
            <v-tooltip v-if="horizontalFlip" location="bottom">
              <template #activator="{ props }">
                <v-icon v-bind="props" icon="swap_horiz" color="blue-darken-1" class="ml-2" />
              </template>
              <span>{{ t('texts.flippedHorizontally') }}</span>
            </v-tooltip>
            <v-tooltip v-if="verticalFlip" location="bottom">
              <template #activator="{ props }">
                <v-icon v-bind="props" icon="swap_vert" color="blue-darken-1" class="ml-2" />
              </template>
              <span>{{ t('texts.flippedVertically') }}</span>
            </v-tooltip>
          </div>
          <v-spacer />
          <div class="pa-2">
            <Transition>
              <div v-show="isHovering || isUserInteracting">
                <ViewerActionRail :view="position.DefaultView" @modal="onActionModal" />
              </div>
            </Transition>
          </div>
        </div>
        <div class="d-flex flex-column">
          <VerticalSliderSelector
            v-if="position.DefaultView === ScanView.Transverse"
            class="px-4 my-0"
            v-model:value="scanState.Orientations.Transverse.Slice"
            v-bind="tMinMax"
          />
          <VerticalSliderSelector
            v-if="position.DefaultView === ScanView.Coronal"
            class="px-4 my-0"
            v-model:value="scanState.Orientations.Coronal.Slice"
            v-bind="cMinMax"
          />
          <VerticalSliderSelector
            v-if="position.DefaultView === ScanView.Sagittal"
            class="px-4 my-0"
            v-model:value="scanState.Orientations.Sagittal.Slice"
            v-bind="sMinMax"
          />
        </div>
      </div>
    </v-hover>
  </div>
</template>

<script setup lang="ts">
import {
  isHorizontalFlip,
  isVerticalFlip,
  cMinMax,
  scanState,
  sMinMax,
  tMinMax,
  isFullscreen,
  previousLayout
} from '@/models/scanState';
import { LayoutActions, PositionData, ScanView, ViewSelectionActions } from '@3cr/types-ts';
import { computed, onMounted, ref, toRefs } from 'vue';
import { storeToRefs } from 'pinia';
import { useViewerStore } from '@/stores/viewer.store';
import { useI18n } from 'vue-i18n';
import { useViewName } from '@/composables/useViewName';
import { forceType } from '@/functions/tsHelper';
import { useViewer3cr } from '@/composables/useViewer3cr';
import { useActiveLayout } from '@/components/modal/layouts/composables/useActiveLayout';

interface Props {
  position: PositionData;
  canvas: HTMLCanvasElement;
  padding?: number;
  radius?: number;
}

const props = withDefaults(defineProps<Props>(), {
  padding: 8,
  radius: 8
});

const { t } = useI18n();
const { activeView, enableMouse, enableKeyboard } = storeToRefs(useViewerStore());
const viewer3cr = useViewer3cr();

const { position, canvas, padding } = toRefs(props);

const anchor = computed(() => position.value.Anchor);
const { layout } = useActiveLayout(anchor, canvas, padding);

const isUserInteracting = ref<boolean>(false);
const container = ref<HTMLDivElement>();

const view = computed(() => position.value.DefaultView);
const horizontalFlip = computed(() => isHorizontalFlip(view.value));
const verticalFlip = computed(() => isVerticalFlip(view.value));

const { name } = useViewName(view);

const viewClass = computed(() => {
  switch (props.position.DefaultView) {
    case ScanView.Volume:
      return 'volume';
    case ScanView.Sagittal:
      return 'sagittal';
    case ScanView.Coronal:
      return 'coronal';
    case ScanView.Transverse:
      return 'transverse';
  }
});

onMounted(() => {
  container.value!.addEventListener('wheel', (e: WheelEvent) => {
    e.preventDefault();
    props.canvas.dispatchEvent(new WheelEvent(e.type, e));
  });

  container.value!.addEventListener(
    'touchstart',
    (e: TouchEvent) => {
      props.canvas.dispatchEvent(new TouchEvent(e.type, forceType<TouchEventInit>(e)));
    },
    { passive: true }
  );

  container.value!.addEventListener(
    'touchmove',
    (e: TouchEvent) => {
      props.canvas.dispatchEvent(new TouchEvent(e.type, forceType<TouchEventInit>(e)));
    },
    { passive: true }
  );

  container.value!.addEventListener(
    'touchend',
    (e: TouchEvent) => {
      props.canvas.dispatchEvent(new TouchEvent(e.type, forceType<TouchEventInit>(e)));
    },
    { passive: true }
  );
  container.value!.addEventListener(
    'touchcancel',
    (e: TouchEvent) => {
      props.canvas.dispatchEvent(new TouchEvent(e.type, forceType<TouchEventInit>(e)));
    },
    { passive: true }
  );

  container.value!.addEventListener('mousedown', (e: MouseEvent) => {
    e.preventDefault();
    props.canvas.dispatchEvent(new MouseEvent(e.type, e));
  });

  container.value!.addEventListener('mouseup', (e: MouseEvent) => {
    e.preventDefault();
    props.canvas.dispatchEvent(new MouseEvent(e.type, e));
  });

  container.value!.addEventListener('contextmenu', (e: Event) => {
    e.preventDefault();
  });
});

function onActionModal(value: boolean): void {
  isUserInteracting.value = value;
}

function onMouseEnter(): void {
  activeView.value = props.position.DefaultView;
  enableMouse.value = true;
  enableKeyboard.value = true;
}

function onMouseLeave(): void {
  activeView.value = undefined;
  enableMouse.value = false;
  enableKeyboard.value = false;
}

async function onDoubleClick(): Promise<void> {
  if (!isFullscreen.value) {
    previousLayout.value = scanState.value.Layout.PositionData;
    await viewer3cr.layouts(LayoutActions.lo01);
    await viewer3cr.viewSelection(`vs_0${view.value + 1}` as ViewSelectionActions);
  } else {
    const message = { Version: '0.0.0', PositionData: previousLayout.value };
    await viewer3cr.customLayout({ message });
    previousLayout.value = [];
  }
}
</script>

<style scoped lang="scss">
@use '@/assets/palette' as p;

.volume {
  cursor: grab;
}

.scan-view {
  left: calc(v-bind('layout.x') * 1px);
  top: calc(v-bind('layout.y') * 1px);
  width: calc(v-bind('layout.width') * 1px);
  height: calc(v-bind('layout.height') * 1px);

  border: transparent 2px dashed;
  border-radius: calc(v-bind('radius') * 1px);
  position: absolute;
  transition:
    border 0.5s linear,
    box-shadow 0.5s linear;
}

.scan-view:hover {
  border: map-get(p.$minsk, 500) 2px dashed;
  box-shadow: 0 0 8px 1px map-get(p.$minsk, 500);
}

.v-enter-active,
.v-leave-active {
  transition: opacity 0.5s linear;
}

.v-enter-from,
.v-leave-to {
  opacity: 0;
}
</style>
