<template>
  <ZoneTiles :key="zoneStore.zone?.id ?? 0" @tileMap:create="tileMap = $event" />
  <ZoneObjects v-if="tileMap" :tilemap="tileMap as Phaser.Tilemaps.Tilemap" />
  <Characters v-if="tileMap" :tilemap="tileMap as Phaser.Tilemaps.Tilemap" />
</template>

<script setup lang="ts">
import { ref, onUnmounted } from 'vue'
import { useScene } from 'phavuer'
import { useGameStore } from '@/stores/gameStore'
import { useZoneStore } from '@/stores/zoneStore'
import { loadZoneTilesIntoScene } from '@/composables/zoneComposable'
import type { Zone as ZoneT, ZoneCharacter } from '@/types'
import ZoneTiles from '@/components/zone/ZoneTiles.vue'
import ZoneObjects from '@/components/zone/ZoneObjects.vue'
import Characters from '@/components/zone/Characters.vue'

const scene = useScene()
const gameStore = useGameStore()
const zoneStore = useZoneStore()

const tileMap = ref(null as Phaser.Tilemaps.Tilemap | null)

type zoneLoadData = {
  zone: ZoneT
  characters: ZoneCharacter[]
}

// Event listeners
gameStore.connection!.on('zone:character:teleport', async (data: zoneLoadData) => {
  /**
   * @TODO : Update character via global event server-side, remove this and listen for it somewhere not here
   */
  gameStore.setCharacter({
    ...gameStore.character!,
    zoneId: data.zone.id
  })

  await loadZoneTilesIntoScene(data.zone, scene)
  zoneStore.setZone(data.zone)
  zoneStore.setCharacters(data.characters)
})

gameStore.connection!.on('zone:character:join', async (data: ZoneCharacter) => {
  // If data is from the current user, don't add it to the store
  if (data.character.id === gameStore.character?.id) return
  zoneStore.addCharacter(data)
})

gameStore.connection!.on('zone:character:leave', (characterId: number) => {
  zoneStore.removeCharacter(characterId)
})

gameStore.connection!.on('character:move', (data: ZoneCharacter) => {
  zoneStore.updateCharacter(data)
})

// Emit zone:character:join event to server and wait for response, then set zone and characters
gameStore!.connection!.emit('zone:character:join', async (response: zoneLoadData) => {
  await loadZoneTilesIntoScene(response.zone, scene)
  zoneStore.setZone(response.zone)
  zoneStore.setCharacters(response.characters)
})

onUnmounted(() => {
  zoneStore.reset()
  gameStore.connection!.off('zone:character:teleport')
  gameStore.connection!.off('zone:character:join')
  gameStore.connection!.off('zone:character:leave')
  gameStore.connection!.off('character:move')
})
</script>
