import { useEngineStore } from "@/stores/EngineStore"
import { useUserinfoStore } from "@/stores/UserinfoStore"
import { useGameinfoStore } from "@/stores/GameinfoStore"
import { useRoundStore } from "@/stores/RoundStore"
import { usePlayersStore } from "@/stores/PlayersStore"
import { EngineContext } from '@/composables/useEngine'

type EngineResponse = {
    version: string,
    game: {
        id: string,
        name: string,
        state: string,
        phase: string,
        round: any,
        players: Array<any>,
    },
}

export async function fetchUpdate(this: EngineContext) {
    if (this.shouldStop || !this.isActive) {
        this.isActive = false
        this.shouldStop = false
        console.debug('engine stopped')
        return
    }

    let delay = 0
    try {
        const userInfoStore = useUserinfoStore()
        const response = await this.callApi('/api/sync', {
            v: '' + (this.version + 1),
            g: userInfoStore.gameId,
        }) as EngineResponse

        if (!Number.isInteger(response.version)) {
            throw Error('unexpected response from /api/sync')
        }

        this.version = parseInt(response.version)
        this.isConnected.value = true
        this.retry.value = 0
        
        useEngineStore().setJson(response)
        useGameinfoStore().setGameinfo(response.game)
        useRoundStore().setRound(response.game.round)
        usePlayersStore().setPlayers(response.game.players)

        // apply rate limit
        const now = new Date()
        const last = this.lastFetched.splice(0, 1)
        this.lastFetched.push(now)
        if (now.getTime() - last[0].getTime() < 1000) {
            console.warn('engine: respawning too fast, throttling down')
            delay = 5000
        }
    } catch (e: any) {
        this.isConnected.value = false
        this.retry.value++

        if (e.response) {
            // callApi() threw an exception
            const { status, statusText } = e.response
            if (status == 200) {
                delay = 1000
            } else {
                console.warn(`HTTP ${status} ${statusText}`)
                if (this.retry.value <= 15) {
                    delay = 1000
                } else {
                    delay = 5000
                }
                this.version = -1
            }
        } else {
            // request aborted or other causes
            console.warn(e.message)

            this.retry.value = -1
            this.isActive = false
            this.shouldStop = false
            console.debug('engine stopped')
            return
        }
    }

    window.setTimeout(() => {
        this.fetchUpdate()
    }, delay)
}