<template>
  <TilemapLayerC :tilemap="tileMap" :tileset="zoneStore.tiles" :layerIndex="0" :cull-padding-x="10" :cull-padding-y="10" />
  <Controls :layer="layer" />
  <Container>
    <Character :layer="layer" v-for="character in zoneStore.characters" :key="character.id" :character="character" />
  </Container>
</template>

<script setup lang="ts">
import config from '@/config'
import Tileset = Phaser.Tilemaps.Tileset
import TilemapLayer = Phaser.Tilemaps.TilemapLayer
import { Container, TilemapLayer as TilemapLayerC, useScene } from 'phavuer'
import Character from '@/components/sprites/Character.vue'
import { type Character as CharacterType } from '@/types'
import { onBeforeMount, onBeforeUnmount, ref, type Ref, watch } from 'vue'
import Controls from '@/components/utilities/Controls.vue'
import { useSocketStore } from '@/stores/socket'
import { useZoneStore } from '@/stores/zone'
import { generateTilemap } from '@/services/zone'

// Phavuer logic
let scene = useScene()
let tilemapLayer = ref()

const tileMap = generateTilemap(scene, 10, 10);
let tileset: Tileset = tileMap.addTilesetImage('default', 'tiles') as Tileset
let layer: TilemapLayer = tileMap.createBlankLayer('layer', tileset, 0, config.tile_size.y) as TilemapLayer

// center camera
const centerY = (tileMap.height * tileMap.tileHeight) / 2
const centerX = (tileMap.width * tileMap.tileWidth) / 2
scene.cameras.main.centerOn(centerX, centerY)

// Multiplayer / server logics
const zoneStore = useZoneStore()
const socket = useSocketStore()

// Watch for changes in the zoneStore and update the layer
watch(
  () => zoneStore.tiles,
  () => {
    // @TODO : change to zone for when loading other maps
    zoneStore.tiles.forEach((row, y) => row.forEach((tile, x) => layer.putTileAt(tile, x, y)))
  },
  { deep: true }
)

// Load the zone from the server
onBeforeMount(() => {
  socket.connection.emit('character:zone:request', { zoneId: socket.character.zoneId })
})

// Listen for the zone event from the server and load the zone
socket.connection.on('character:zone:load', (data) => {
  console.log('character:zone:load', data)
  zoneStore.setTiles(data.zone.tiles)

  let characters = data.characters
  zoneStore.setCharacters(characters)
})

// Listen for player join events
socket.connection.on('zone:character:join', (data: CharacterType) => {
  console.log('character:zone:join', data)
  zoneStore.addCharacter(data)
})

// Listen for user:disconnect
socket.connection.on('zone:character:leave', (data: CharacterType) => {
  zoneStore.removeCharacter(data)
})

socket.connection.on('character:moved', (data: CharacterType) => {
  console.log('character:moved', data)
  zoneStore.updateCharacter(data)
})

onBeforeUnmount(() => {
  zoneStore.reset();
  socket.connection.emit('character:zone:leave')
  socket.connection.off('character:zone:load')
  socket.connection.off('zone:character:join')
  socket.connection.off('user:disconnect')
  socket.connection.off('character:moved')
})

/**
 * 1 tile is 64x32
 * the zone is 10x10
 * so the zone is 640x320
 */
/**
 * Resources
 * https://clintbellanger.net/articles/isometric_math/
 * https://gist.github.com/veleek/3be73dc61d5f5a80abc0f72c3ffe390e
 * https://gamedev.stackexchange.com/questions/116485/how-to-center-a-tilemap-in-phaser
 * https://github.com/Nulligma/phaser-isometric-test/blob/master/src/main.ts
 * https://github.com/neki-dev/isometric-snippets
 * https://github.com/itsezc/CycloneIO/blob/next/packages/client/games/HabboEngine.ts
 * https://github.com/daan93/phaser-isometric-demo/tree/main
 */
</script>
