import { Server } from 'socket.io'

import { BaseService } from '#application/base/baseService'
import { ExtendedCharacter, TSocket } from '#application/types'
import { ZoneEventTileTeleport } from '#entities/zoneEventTileTeleport'
import ZoneManager from '#managers/zoneManager'

class ZoneEventTileService extends BaseService {
  public async handleTeleport(io: Server, socket: TSocket, character: ExtendedCharacter, teleport: ZoneEventTileTeleport): Promise<void> {
    if (teleport.toZone.id === character.zone.id) return

    const loadedZone = ZoneManager.getZoneById(teleport.toZone.id)
    if (!loadedZone) {
      this.logger.error('zone:character:join error: Loaded zone not found')
      return
    }

    const zone = loadedZone.getZone()

    const oldZoneId = character.zone.id
    const newZoneId = teleport.toZone.id

    character.isMoving = false
    // Update local character object
    character.setZone(teleport.toZone).setRotation(teleport.toRotation).setPositionX(teleport.toPositionX).setPositionY(teleport.toPositionY)

    await character.save()

    // Remove and add character to new zone
    await loadedZone.removeCharacter(character.id)
    loadedZone.addCharacter(character)

    // Emit events
    io.to(oldZoneId.toString()).emit('zone:character:leave', character.id)
    io.to(newZoneId.toString()).emit('zone:character:join', character)

    // Update socket rooms
    socket.leave(oldZoneId.toString())
    socket.join(newZoneId.toString())

    // Send teleport information to the client
    socket.emit('zone:character:teleport', {
      zone,
      characters: loadedZone.getCharactersInZone()
    })
  }
}

export default new ZoneEventTileService()