import type { PJ } from '@lastres/pj'
import type { Location } from '@lastres/location'
import type InputPacket from '@lastres/input-packet'
import type { LogLine } from '@lastres/log-line'
import InputPacketInfo from '@lastres/input-packet/info'
import InputPacketPong from '@lastres/input-packet/pong'
type SetTeamPJs = (set: PJ[] | null) => void
type SetCurrentLocation = (set: Location | null) => void
type SetConnectedLocations = (set: Location[] | null) => void
type DispatchHash = Record<string, any>
type SetLogLines = (set: LogLine[] | null) => void
interface Packet {
    command: string
    data: any
}
export default class InputPackets {
    setTeamPJs: SetTeamPJs
    setCurrentLocation: SetCurrentLocation
    setConnectedLocations: SetConnectedLocations
    setLogLines: SetLogLines
    cachedHash: DispatchHash | null = null
    cachedArray: InputPacket[] | null = null
    constructor (setTeamPJs: SetTeamPJs,
        setCurrentLocation: SetCurrentLocation,
        setConnectedLocations: SetConnectedLocations,
        setLogLines: SetLogLines) {
        this.setTeamPJs = setTeamPJs
        this.setCurrentLocation = setCurrentLocation
        this.setConnectedLocations = setConnectedLocations
        this.setLogLines = setLogLines
    }

    handle (packet: Packet): void {
        const hash = this.hashAvailablePackets()
        const identifier = packet.command
        const inputPacket = hash[identifier]
        inputPacket.recv(packet)
    }

    listAvailablePackets (): InputPacket[] {
        if (this.cachedArray === null) {
            const infoPacket = new InputPacketInfo()
            const pongPacket = new InputPacketPong()
            infoPacket.onReceive((data) => {
                this.setTeamPJs(data.team_pjs)
                this.setConnectedLocations(data.location_data.connected_places)
                this.setCurrentLocation(data.location_data.current)
                this.setLogLines(data.set_log)
            })
            this.cachedArray = [infoPacket, pongPacket]
        }
        return this.cachedArray
    }

    hashAvailablePackets (): DispatchHash {
        if (this.cachedHash === null) {
            this.cachedHash = {}
            for (const inputPacket of this.listAvailablePackets()) {
                this.cachedHash[inputPacket.identifier()] = inputPacket
            }
        }
        return this.cachedHash
    }
}
