import CryptoJS from 'crypto-js'
import { onBeforeUnmount, onMounted } from 'vue'
import { $read_socket_storge, $remove_socket_storage, $notify } from '@/commons/utils'
import { initSocket, onSocketMessage, sendSocketMessage } from '@/commons/ws'
import router from '@/router'

type SocketPayload = {
    msg?: string
    state?: number
    data?: any
}

type AdminGameSocketOptions = {
    gameId?: string,
    loginRedirectPath?: string
    onConnect?: () => boolean
    onRoomState?: (data: any) => void
    onRoomJoin?: (data: any) => void
    onGameStart?: (data: any) => void | Promise<void>
    onRoomRank?: (data: any) => void
    onRelogin?: () => void
    onAny?: (evt: string, data: any) => void
}

export function useAdminGameSocket(options: AdminGameSocketOptions) {
    let offSocketMessage: (() => void) | undefined

    function requestRoomState() {
        return sendSocketMessage('room_state')
    }

    function createRoom(index: number) {
        return sendSocketMessage('room_create', index)
    }
    function backRoom(index: number) {
        return sendSocketMessage('room_back', index)
    }

    function startGame() {
        return sendSocketMessage('game_start', options.gameId)
    }

    function sendAdminMessage(cmd: string, data: any = {}) {
        return sendSocketMessage(cmd, data)
    }

    function closeRoom() {
        return sendSocketMessage('room_close', {})
    }

    onMounted(() => {
        const { passphrase, token, socket_path, client_ns, domain } = $read_socket_storge()
        let socket = initSocket({
            socket_path: `${domain}${socket_path}`,
            client_ns,
            auth: {
                userid: token,
                validuser: CryptoJS.AES.encrypt(token, passphrase).toString(),
            },
            onConnect: () => {
                if (options.onConnect) {
                    if (!options.onConnect()) {
                        return;
                    }
                }
                window.setTimeout(requestRoomState, 200)
            },
            onDisconnect: (_reason: string) => {

            },
            onError: (error: any) => {
                // console.error('socket.io connect_error:', error)
            },
        })

        offSocketMessage = onSocketMessage(async (evt, payload: SocketPayload) => {
            const { msg, state, data } = payload
            if (state === 0) {
                if (evt == 'login_result') {
                    // alert(msg)
                    // options.onRelogin?.()
                    // $notify(msg);
                    $remove_socket_storage();
                    await router.replace(`/login`);
                    return;
                }
                else if (evt == 'new_admin_result') {
                    // alert(msg);
                    // $notify(msg);
                    $remove_socket_storage();
                    await router.replace(`/login`);
                    return;
                }
            }

            switch (evt) {
                case 'room_state_result': {
                    if (data.gameId) {
                        //如果这两个值不一致说明浏览器有直接更新游戏房间号
                        if (data.gameId != options.gameId) {
                            // location.reload();
                            return;
                        }
                    }
                    options.onRoomState?.(data)
                    return
                }
                case 'player_offline_result': {
                    // $notify('有玩家掉线')
                    if (data)
                        options.onRoomJoin?.(data)
                    return
                }
                case 'room_join_result': {
                    options.onRoomJoin?.(data)
                    return
                }
                case 'game_start_result': {
                    if (data === options.gameId) {
                        await options.onGameStart?.(data)
                    }
                    return
                }
                case 'room_rank_result': {
                    options.onRoomRank?.(data)
                    return
                }
            }
            options?.onAny?.(evt, payload);
        })
    })

    onBeforeUnmount(() => {
        offSocketMessage?.()
    })

    return {
        requestRoomState,
        createRoom,
        backRoom,
        startGame,
        sendAdminMessage,
        closeRoom,
    }
}
