import React, { useEffect, useState } from "react";
import { commands, GameSettings, LobbyState, PingStartCondition, PlayerProfile } from "@/bindings";
import { useTauriEvent } from "@/lib/hooks";
import ProfilePicture, { iconForDecor, ProfileDecor } from "./ProfilePicture";
import { defaultSettings } from "./MenuScreen";
import { ask } from "@tauri-apps/plugin-dialog";
import {
    IconArrowBigLeftLinesFilled,
    IconCircleCheckFilled,
    IconCircleDashedPlus,
    IconFlagFilled,
    IconInfoCircleFilled,
    IconSettingsFilled
} from "@tabler/icons-react";
import LoadingCover from "./LoadingCover";
import GameSettingsModal from "./game-settings/GameSettingsModal";

function ProfileList({
    profiles,
    decoration,
    emptyText
}: {
    profiles: [string, PlayerProfile][];
    decoration: ProfileDecor;
    emptyText: string;
}) {
    return (
        <div className="pfp-list">
            {profiles.length === 0 && <small>{emptyText}</small>}
            {profiles.map(([k, p]) => (
                <ProfilePicture
                    key={k}
                    decoration={decoration}
                    src={p.pfp_base64}
                    fallbackName={p.display_name}
                />
            ))}
        </div>
    );
}

function TeamButton({
    onClick,
    active,
    deco,
    text
}: {
    onClick: () => void;
    active: boolean;
    deco: ProfileDecor;
    text: string;
}) {
    const Icon = iconForDecor(deco);

    return (
        <button onClick={onClick} className={`team-button ${deco}`}>
            <Icon />
            {active ? "You're On" : "Join"} {text}
            {active ? <IconCircleCheckFilled /> : <IconCircleDashedPlus />}
        </button>
    );
}

const initLobbyState: LobbyState = {
    profiles: {},
    join_code: "",
    teams: {},
    self_id: "",
    is_host: false,
    settings: defaultSettings()
};

export default function LobbyScreen() {
    const [lobbyState, setLobbyState] = useState(initLobbyState);
    const [loadingCover, setLoadingCover] = useState(true);
    const [settingOpen, setSettingsOpen] = useState(false);

    useEffect(() => {
        let cancel = false;
        const clear = setTimeout(() => {
            commands.getLobbyState().then((state) => {
                if (!cancel) {
                    setLobbyState(state);
                    setLoadingCover(false);
                }
            });
        }, 300);
        return () => {
            cancel = true;
            clearTimeout(clear);
        };
    }, [setLobbyState]);

    useTauriEvent("lobbyStateUpdate", () => {
        commands.getLobbyState().then((state) => {
            setLobbyState(state);
        });
    });

    const profiles = Object.entries(lobbyState.profiles).filter(([_, p]) => p !== undefined) as [
        string,
        PlayerProfile
    ][];

    const seekers = profiles.filter(([id, _]) => lobbyState.teams[id] ?? false);
    const hiders = profiles.filter(([id, _]) => !(lobbyState.teams[id] ?? false));

    const isSeeker = lobbyState.teams[lobbyState.self_id] ?? false;

    const onLeaveLobby = () => {
        // Don't prompt since the lobby is empty (besides us obv)
        // <= even though it should never be 0... hopefully....
        if (lobbyState.is_host && profiles.length <= 1) {
            commands.quitToMenu();
            return;
        }
        const hostMsg = lobbyState.is_host ? " You are the host so this will cancel the lobby" : "";

        const msg = `Are you sure you want to leave this lobby?${hostMsg}`;

        ask(msg, {
            title: "Leave Lobby",
            kind: lobbyState.is_host ? "warning" : "info"
        }).then((choice) => {
            if (choice) {
                commands.quitToMenu();
            }
        });
    };

    const canStart = lobbyState.is_host && seekers.length !== 0 && hiders.length !== 0;

    const onStartGame = () => {
        if (canStart) {
            setLoadingCover(true);
            ask(
                "Are you ready to start the game? New players will be unable to join. The hiding timer will begin the moment you press start."
            )
                .then((choice) => {
                    if (choice) {
                        commands.hostStartGame().finally(() => {
                            setLoadingCover(false);
                        });
                    } else {
                        setLoadingCover(false);
                    }
                })
                .catch(() => {
                    setLoadingCover(false);
                });
        }
    };

    const onOpenSettings = () => {
        setSettingsOpen(true);
    };

    const onSettingsSave = (settings: GameSettings) => {
        commands.hostUpdateSettings(settings);
        setSettingsOpen(false);
    };

    return (
        <>
            <LoadingCover show={loadingCover} />
            {settingOpen && (
                <GameSettingsModal gameSettings={lobbyState.settings} onSave={onSettingsSave} />
            )}
            <header>
                <span className="grow">Lobby</span>
                <span>Join: {lobbyState.join_code}</span>
            </header>
            <main className="lobby">
                <ProfileList profiles={seekers} decoration="seeker" emptyText="No Seekers" />
                <TeamButton
                    onClick={() => commands.switchTeams(true)}
                    active={isSeeker}
                    text="Seekers"
                    deco="seeker"
                />
                <div className="frame">
                    <button onClick={onLeaveLobby} className="fab tl">
                        <IconArrowBigLeftLinesFilled size="1.5em" />
                        Leave
                    </button>
                    {lobbyState.is_host && (
                        <button onClick={onOpenSettings} className="fab bl">
                            <IconSettingsFilled size="1.5em" />
                            Rules
                        </button>
                    )}
                    {lobbyState.is_host && (
                        <button disabled={!canStart} onClick={onStartGame} className="fab br">
                            <IconFlagFilled size="1.5em" />
                            Start
                        </button>
                    )}
                </div>
                <TeamButton
                    onClick={() => commands.switchTeams(false)}
                    active={!isSeeker}
                    text="Hiders"
                    deco="hider"
                />
                <ProfileList profiles={hiders} decoration="hider" emptyText="No Hiders" />
            </main>
        </>
    );
}
