<template>
  <nav class="[&>*]:m-3 text-black w-48">
    <div class="flex flex-col ui">
      <button @click="resetView">home</button>
      <button @click="addPoint">Add Point</button>
      <div class="flex flex-col my-6">
        <button
          v-for="marker in sortedMarkers"
          :key="marker.order"
          @click="selectMarker(marker)"
          :class="marker.id === selectedMarker.id ? 'text-green-500 text-bold' : ''"
        >
          {{ marker.name }}
        </button>
      </div>
      <div v-if="isAMarkerSelected">
        <input
          ref="textInputMarkerName"
          type="text"
          v-model="selectedMarker.name"
          class="w-40 my-4"
        />
        <textarea v-model="selectedMarker.annotation" class="w-40 h-40"></textarea>
        <button @click="saveMarker">Save</button>
        <button @click="unselectMarker">Cancel</button>
      </div>
    </div>
  </nav>
</template>

<script setup lang="ts">
import type { Story, Marker } from '@/types/virages'
import { onMounted, ref, inject, nextTick, type Ref, computed } from 'vue'
import OpenSeadragon from 'openseadragon'
import { useIsMobile } from '@/composables/IsMobile'
import { useViewer } from '@/composables/Viewer'
import { useStoryStore } from '@/stores/story'
import { useEscapeKey } from '@/composables/EscapeKey'

const props = defineProps<{ story: Story }>()
const Viewer = inject<Ref<OpenSeadragon.Viewer>>('Viewer')
const selectedMarker = ref<Marker>({} as Marker)
const textInputMarkerName = ref<HTMLInputElement | null>(null)
const {
  zoomTo,
  goHome,
  enableMouseNav,
  disableMouseNav,
  injectMarker,
  addClickHandler,
  removeClickHandler,
  getZoom,
  getBounds,
  pointFromPixel,
} = useViewer(Viewer)
const store = useStoryStore()
const isAMarkerSelected = computed(() => {
  return selectedMarker.value.id !== undefined
})
const sortedMarkers = computed(() => {
  return [...props.story.markers].sort((a, b) => a.order - b.order)
})

const resetView = () => {
  goHome()
  unselectMarker()
}

const addPoint = () => {
  unselectMarker()
  createMarkerOnClick()
  document.querySelector('.openseadragon-canvas')?.classList.add('cursor-crosshair')
}

const saveMarker = () => {
  unselectMarker()
}

const selectMarker = (marker: Marker) => {
  document.querySelectorAll('.marker-selected').forEach((el) => {
    el.classList.remove('marker-selected')
  })
  const theMarker = document.querySelector('.marker-id-' + marker.id)
  theMarker?.classList.add('marker-selected')
  const markerRectangle = new OpenSeadragon.Rect(
    marker.bounds.x,
    marker.bounds.y,
    marker.bounds.width,
    marker.bounds.height,
  )
  Viewer?.value.viewport.fitBoundsWithConstraints(markerRectangle, false)
  selectedMarker.value = marker
  nextTick(() => {
    const isMobile = useIsMobile()
    if (!isMobile) {
      textInputMarkerName.value?.focus()
    }
  })
}

const unselectMarker = () => {
  selectedMarker.value = {} as Marker
  document.querySelector('.marker-selected')?.classList.remove('marker-selected')
}

const createMarker = (marker: Marker) => {
  const overlay = document.createElement('button')
  overlay.className = `marker-id-${marker.id} marker`
  overlay.title = marker.name
  overlay.onfocus = function () {
    selectMarker(marker)
  }
  overlay.addEventListener('click', function () {
    selectMarker(marker)
  })
  overlay.addEventListener('mouseover', function () {
    disableMouseNav()
  })
  overlay.addEventListener('mouseout', function () {
    enableMouseNav()
  })
  injectMarker(marker, overlay)
}

const createMarkerOnClick = () => {
  const addPointhandler = addClickHandler((event) => {
    const newMarker: Marker = {
      id: props.story.markers.length,
      order: props.story.markers.length,
      name: '',
      bounds: getBounds(),
      point: pointFromPixel(event.position),
      zoom: getZoom(),
      annotation: '',
    }
    store.addMarker(props.story, newMarker)
    createMarker(newMarker)
    document.querySelector('.openseadragon-canvas')?.classList.remove('cursor-crosshair')
    selectMarker(newMarker)
    removeClickHandler(addPointhandler)
  })
}

const editMarkerOnDragOrZoom = () => {
  Viewer?.value.addHandler('canvas-drag', (event) => {
    if (isAMarkerSelected.value) {
      Viewer.value.gestureSettingsMouse.dragToPan = false
      const point = Viewer?.value.viewport.pointFromPixel(event.position)
      selectedMarker.value.point = point
      selectedMarker.value.bounds = Viewer?.value.viewport.getBounds()
      const overlay = document.querySelector('.marker-id-' + selectedMarker.value.id)
      Viewer?.value.updateOverlay(overlay as Element, point)
    }
  })

  Viewer?.value.addHandler('canvas-release', () => {
    Viewer.value.gestureSettingsMouse.dragToPan = true
  })

  Viewer?.value.addHandler('zoom', (event) => {
    if (isAMarkerSelected.value) {
      selectedMarker.value.zoom = event.zoom
      selectedMarker.value.bounds = Viewer?.value.viewport.getBounds()
    }
  })
}

const loadStory = (markers: Marker[]) => {
  markers.forEach((marker) => {
    createMarker(marker)
  })
}

const initScalebar = () => {
  Viewer.value.scalebar({
    type: OpenSeadragon.ScalebarType.MAP,
    pixelsPerMeter: 1000000,
    minWidth: '74px',
    location: OpenSeadragon.ScalebarLocation.BOTTOM_RIGHT,
    color: 'black',
    fontColor: 'black',
    backgroundColor: 'rgba(255, 255, 255, 0.5)',
    barThickness: 1,
    stayInsideImage: false,
    xOffset: 20,
    yOffset: 20,
  })
}

useEscapeKey(() => {
  unselectMarker()
  resetView()
})

onMounted(() => {
  nextTick(() => {
    Viewer?.value.clearOverlays()
    // Viewer.value.viewport.defaultZoomLevel = 1
    loadStory(props.story.markers)
    editMarkerOnDragOrZoom()
    initScalebar()
    Viewer.value.bookmarkUrl()
    zoomTo(6) // COMPOSABLE WORKS
  })
})
</script>

<style>
.ui button {
  @apply border-2 border-black px-4 py-2 rounded-xl bg-slate-300 hover:bg-neutral-100 m-1;
}
.ui input,
.ui textarea {
  @apply border-2 border-black px-4 py-2;
}
.marker {
  @apply w-8 h-8 rounded-full shadow-2xl bg-green-500 bg-opacity-50 hover:bg-green-600 hover:bg-opacity-100  hover:cursor-pointer pointer-events-auto hover:scale-150 transition-all border-2 border-white border-8 transform -translate-y-1/2 -translate-x-1/2;
}
.marker-selected {
  @apply border-blue-400 border-8 bg-white animate-pulse hover:cursor-move hover:bg-white;
}
</style>
