<template>
  <MapTiles v-if="tileMap && tileMapLayer" :tileMap :tileMapLayer />
  <PlacedMapObjects v-if="tileMap && tileMapLayer" :tileMap :tileMapLayer />
  <Characters v-if="tileMap && mapStore.characters" :tileMap />
</template>

<script setup lang="ts">
import type { mapLoadData } from '@/application/types'
import { unduplicateArray } from '@/application/utilities'
import Characters from '@/components/game/map/Characters.vue'
import MapTiles from '@/components/game/map/MapTiles.vue'
import PlacedMapObjects from '@/components/game/map/PlacedMapObjects.vue'
import { createTileLayer, createTileMap, loadTileTexturesFromMapTileArray } from '@/services/mapService'
import { MapStorage } from '@/storage/storages'
import { useGameStore } from '@/stores/gameStore'
import { useMapStore } from '@/stores/mapStore'
import { useScene } from 'phavuer'
import { onMounted, onUnmounted, shallowRef, watch } from 'vue'

const scene = useScene()

const gameStore = useGameStore()
const mapStore = useMapStore()

const mapStorage = new MapStorage()

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

// Event listeners
gameStore.connection?.on('map:character:teleport', async (data: mapLoadData) => {
  mapStore.setMapId(data.mapId)
  mapStore.setCharacters(data.characters)
})

async function initialize() {
  if (!mapStore.mapId) return

  const map = await mapStorage.get(mapStore.mapId)
  if (!map) return

  await loadTileTexturesFromMapTileArray(mapStore.mapId, scene)

  tileMap.value = createTileMap(scene, map)
  tileMapLayer.value = createTileLayer(tileMap.value, unduplicateArray(map.tiles.flat()))
}

watch(
  () => mapStore.mapId,
  async () => {
    await initialize()
  }
)

onMounted(async () => {
  if (!mapStore.mapId) return
  await initialize()
})

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

  gameStore.connection?.off('map:character:teleport')
})
</script>