<template>
  <MapTiles ref="mapTiles" v-if="tileMap && tileMapLayer" :tileMap :tileMapLayer />
  <PlacedMapObjects ref="mapObjects" v-if="tileMap && tileMapLayer" :tileMap :tileMapLayer />
  <MapEventTiles ref="eventTiles" v-if="tileMap" :tileMap />
</template>

<script setup lang="ts">
import MapEventTiles from '@/components/gameMaster/mapEditor/mapPartials/MapEventTiles.vue'
import MapTiles from '@/components/gameMaster/mapEditor/mapPartials/MapTiles.vue'
import PlacedMapObjects from '@/components/gameMaster/mapEditor/mapPartials/PlacedMapObjects.vue'
import { useMapEditorComposable } from '@/composables/useMapEditorComposable'
import { createTileLayer, createTileMap } from '@/services/mapService'
import { TileStorage } from '@/storage/storages'
import { useScene } from 'phavuer'
import { onBeforeUnmount, onMounted, onUnmounted, shallowRef, useTemplateRef } from 'vue'

const tileMap = shallowRef<Phaser.Tilemaps.Tilemap>()
const tileMapLayer = shallowRef<Phaser.Tilemaps.TilemapLayer>()

const mapEditor = useMapEditorComposable()

const scene = useScene()

const mapTiles = useTemplateRef('mapTiles')
const mapObjects = useTemplateRef('mapObjects')
const eventTiles = useTemplateRef('eventTiles')

function handlePointerDown(pointer: Phaser.Input.Pointer) {
  if (!mapTiles.value || !mapObjects.value || !eventTiles.value) return

  // Check if left mouse button is pressed
  if (!pointer.isDown) return

  // Check if shift is not pressed, this means we are moving the camera
  if (pointer.event.shiftKey) return

  // Check if draw mode is tile
  switch (mapEditor.drawMode.value) {
    case 'tile':
      mapTiles.value.handlePointer(pointer)
      break
    case 'map_object':
      mapObjects.value.handlePointer(pointer)
      break
    case 'teleport':
      eventTiles.value.handlePointer(pointer)
      break
    case 'blocking tile':
      eventTiles.value.handlePointer(pointer)
      break
  }
}

function handleKeyDown(event: KeyboardEvent) {
  //CTRL+Y
  if (event.key === 'y' && event.ctrlKey) {
    mapTiles.value!.redo()
  }

  //CTRL+Z
  if (event.key === 'z' && event.ctrlKey) {
    mapTiles.value!.undo()
  }
}

function handlePointerMove(pointer: Phaser.Input.Pointer) {
  if (mapEditor.inputMode.value === 'hold' && pointer.isDown) {
    handlePointerDown(pointer)
  }
}

function handlePointerUp(pointer: Phaser.Input.Pointer) {
  if (mapEditor.drawMode.value === 'tile') {
    mapTiles.value?.finalizeCommand()
  }
}

onMounted(async () => {
  let mapValue = mapEditor.currentMap.value
  if (!mapValue) return

  const tileStorage = new TileStorage()
  const allTiles = await tileStorage.getAll()
  const allTileIds = allTiles.map((tile) => tile.id)

  tileMap.value = createTileMap(scene, mapValue)
  tileMapLayer.value = createTileLayer(tileMap.value, allTileIds)

  addEventListener('keydown', handleKeyDown)
  scene.input.on(Phaser.Input.Events.POINTER_DOWN, handlePointerDown)
  scene.input.on(Phaser.Input.Events.POINTER_MOVE, handlePointerMove)
  scene.input.on(Phaser.Input.Events.POINTER_UP, handlePointerUp)
})

onUnmounted(() => {
  if (tileMap.value) {
    tileMap.value.destroyLayer('tiles')
    tileMap.value.removeAllLayers()
    tileMap.value.destroy()
  }

  scene.input.off(Phaser.Input.Events.POINTER_DOWN, handlePointerDown)
  scene.input.off(Phaser.Input.Events.POINTER_MOVE, handlePointerMove)
  scene.input.off(Phaser.Input.Events.POINTER_UP, handlePointerUp)
  mapEditor.reset()
})

onBeforeUnmount(() => {
  removeEventListener('keydown', handleKeyDown)
})
</script>
