import * as React from 'react'

import type { PJ } from '@lastres/pj'
import type { Location } from '@lastres/location'
import type { LogLine } from '@lastres/log-line'

import UpperPanel from '@lastres/components/upper-panel'
import BottomPanel from '@lastres/components/bottom-panel'
import PJSelectionMenu from '@lastres/components/pj-selection-menu'
import OutputPacketInit from '@lastres/output-packet/init'
import OutputPacketPing from '@lastres/output-packet/ping'
import InputPackets from '@lastres/input-packets'

export interface GameProps {
    setSelectedPJ: (set: PJ | null) => void
    selectedPJ: PJ | null
    userWantsToCreatePJ: boolean
    setUserWantsToCreatePJ: (set: boolean) => void
    error: string | null
    setError: (set: string | null) => void
}

export default function Game (props: GameProps): JSX.Element {
    const selectedPJ = props.selectedPJ
    if (selectedPJ === null) {
        return (
            <>
                <PJSelectionMenu
                    setSelectedPJ={props.setSelectedPJ}
                    userWantsToCreatePJ={props.userWantsToCreatePJ}
                    setUserWantsToCreatePJ={props.setUserWantsToCreatePJ}
                    error={props.error}
                    setError={props.setError}/>
            </>
        )
    }
    const [websocket, setWebsocket] = React.useState<WebSocket | null>(null)
    const [teamPJs, setTeamPJs] = React.useState<PJ[] | null>(null)
    const [currentLocation, setCurrentLocation] = React.useState<Location | null>(null)
    const [connectedLocations, setConnectedLocations] = React.useState<Location[] | null>(null)
    const [logLines, setLogLines] = React.useState<LogLine[] | null>(null)
    if (websocket === null) {
        window.setTimeout(() => {
            const locationProtocol = window.location.protocol
            if (locationProtocol == null) {
                return
            }
            const protocol = locationProtocol.match(/https:/) != null ? 'wss' : 'ws'
            const webSocket = new WebSocket(`${protocol}://${window.location.host}/ws`)
            webSocket.onopen = () => {
                new OutputPacketInit(selectedPJ.uuid).send(webSocket)
                let interval: number = 0
                interval = window.setInterval(() => {
                    if (webSocket.readyState === WebSocket.OPEN) {
                        new OutputPacketPing().send(webSocket)
                        return
                    }
                    window.clearInterval(interval)
                }, 10000)
            }
            const inputPackets = new InputPackets(setTeamPJs, setCurrentLocation, setConnectedLocations, setLogLines)
            webSocket.onmessage = (event) => {
                const packet = JSON.parse(event.data)
                inputPackets.handle(packet)
            }
            webSocket.onerror = (event) => {
                console.log(event)
            }
            setWebsocket(webSocket)
        }, 1)
    }
    return (
        <>
            <UpperPanel teamPJs={teamPJs}
                currentLocation={currentLocation}
                connectedLocations={connectedLocations}
                logLines={logLines}/>
            <BottomPanel/>
        </>
    )
}
