/*
 * This file is part of laurelin/client
 * Copyright (C) 2023 Jonni Liljamo <jonni@liljamo.com>
 *
 * Licensed under GPL-3.0-only.
 * See LICENSE for licensing information.
 */

use bevy::prelude::*;
use bevy_egui::{egui, EguiContexts};
use laurelin_shared::types::{
    game::{GamePub, GAMESTATE_FINISHED, GAMESTATE_FORMING, GAMESTATE_INPROGRESS},
    user::UserPub,
};

use crate::{
    cfg::CfgUser,
    plugins::{
        menu::MenuState,
        networking::send::game::{GameAllFormingEvent, GameCreateEvent, GameMyGamesEvent},
    },
    util::egui::menuwindow,
    Global,
};

use super::{PlayScreenBrowseState, PlayScreenData, PlayScreenState};

pub fn ui(
    mut commands: Commands,
    mut egui_contexts: EguiContexts,
    mut data: ResMut<PlayScreenData>,
    cfg_user: Res<CfgUser>,
    mut global: ResMut<Global>,
    mut creategame_ev_w: EventWriter<GameCreateEvent>,
    mut allforming_ev_w: EventWriter<GameAllFormingEvent>,
    mut mygames_ev_w: EventWriter<GameMyGamesEvent>,
) {
    menuwindow(
        egui_contexts.ctx_mut(),
        data.state.clone().display(),
        &egui::Vec2::new(800., 600.),
        |ui| match data.state {
            PlayScreenState::Main => {
                egui::SidePanel::left("play_side_panel")
                    .resizable(false)
                    .show_inside(ui, |ui| {
                        ui.vertical_centered(|ui| {
                            if ui.button("Create").clicked() {
                                data.state = PlayScreenState::CreateGame;
                            }

                            if ui.button("Back").clicked() {
                                commands.insert_resource(NextState(Some(MenuState::Menu)));
                            }
                        });
                    });

                egui::TopBottomPanel::top("play_top_panel")
                    .resizable(false)
                    .show_inside(ui, |ui| {
                        ui.horizontal(|ui| {
                            ui.label(egui::RichText::new("Browse: ").size(24.));

                            ui.selectable_value(
                                &mut data.browse_state,
                                PlayScreenBrowseState::Forming,
                                "Forming",
                            );
                            ui.selectable_value(
                                &mut data.browse_state,
                                PlayScreenBrowseState::InProgress,
                                "In Progress",
                            );
                            ui.selectable_value(
                                &mut data.browse_state,
                                PlayScreenBrowseState::Finished,
                                "Finished",
                            );

                            ui.with_layout(
                                egui::Layout::right_to_left(egui::Align::Center),
                                |ui| {
                                    if ui.button("Refresh").clicked() {
                                        match data.browse_state {
                                            PlayScreenBrowseState::Forming => {
                                                if !data.waiting_for_all_forming {
                                                    allforming_ev_w.send(GameAllFormingEvent);
                                                }
                                            }
                                            PlayScreenBrowseState::InProgress => {
                                                if !data.waiting_for_my_games {
                                                    mygames_ev_w.send(GameMyGamesEvent);
                                                }
                                            }
                                            PlayScreenBrowseState::Finished => {
                                                if !data.waiting_for_my_games {
                                                    mygames_ev_w.send(GameMyGamesEvent);
                                                }
                                            }
                                        }
                                    }
                                },
                            );
                        });
                    });

                ui.vertical_centered(|ui| {
                    egui::ScrollArea::vertical().show(ui, |ui| match data.browse_state {
                        PlayScreenBrowseState::Forming => {
                            browse_forming(ui, &mut data, &cfg_user, &mut global);
                        }
                        PlayScreenBrowseState::InProgress => {
                            browse_inprogress(ui, &mut data, &mut global, &cfg_user);
                        }
                        PlayScreenBrowseState::Finished => {
                            browse_finished(ui, &mut data, &global, &cfg_user);
                        }
                    });
                });
            }
            PlayScreenState::CreateGame => {
                ui.vertical_centered(|ui| {
                    ui.add_enabled_ui(!data.waiting_for_create_game, |ui| {
                        if ui.button("Confirm").clicked() {
                            data.waiting_for_create_game = true;
                            creategame_ev_w.send(GameCreateEvent);
                        }

                        if ui.button("Cancel").clicked() {
                            data.state = PlayScreenState::Main;
                        }
                    });
                });
            }
            PlayScreenState::InLobbyHost => {
                ui.label(egui::RichText::new(format!(
                    "Host: {}",
                    global
                        .users_cache
                        .get(&global.cur_game.as_ref().unwrap().host_id)
                        .unwrap_or(&UserPub {
                            id: "".to_string(),
                            created_at: "".to_string(),
                            username: "N/A".to_string()
                        })
                        .username
                )));

                ui.label(egui::RichText::new(format!(
                    "Guest: {}",
                    global
                        .users_cache
                        .get(
                            global
                                .cur_game
                                .as_ref()
                                .unwrap()
                                .guest_id
                                .as_ref()
                                .unwrap_or(&"".to_string())
                        )
                        .unwrap_or(&UserPub {
                            id: "".to_string(),
                            created_at: "".to_string(),
                            username: "N/A".to_string()
                        })
                        .username
                )));

                if ui.button("Start").clicked() {
                    //startgame_ev_w.send(StartGameEvent);
                }

                if ui.button("Back").clicked() {
                    data.state = PlayScreenState::Main;
                }
            }
            PlayScreenState::InLobbyGuest => {
                ui.label(egui::RichText::new(format!(
                    "Host: {}",
                    global
                        .users_cache
                        .get(&global.cur_game.as_ref().unwrap().host_id)
                        .unwrap_or(&UserPub {
                            id: "".to_string(),
                            created_at: "".to_string(),
                            username: "N/A".to_string()
                        })
                        .username
                )));

                ui.label(egui::RichText::new(format!(
                    "Guest: {}",
                    global
                        .users_cache
                        .get(
                            global
                                .cur_game
                                .as_ref()
                                .unwrap()
                                .guest_id
                                .as_ref()
                                .unwrap_or(&"".to_string())
                        )
                        .unwrap_or(&UserPub {
                            id: "".to_string(),
                            created_at: "".to_string(),
                            username: "N/A".to_string()
                        })
                        .username
                )));

                if ui.button("Back").clicked() {
                    data.state = PlayScreenState::Main;
                }
            }
        },
    );
}

fn browse_forming(
    ui: &mut egui::Ui,
    data: &mut PlayScreenData,
    cfg_user: &CfgUser,
    global: &mut Global,
) {
    if data.waiting_for_all_forming {
        ui.horizontal(|ui| {
            ui.spinner();
            ui.label("loading...");
        });
        return;
    }

    let mut all_forming: Vec<&GamePub> = global
        .games_cache
        .values()
        .filter(|g| g.state == GAMESTATE_FORMING)
        .collect();

    // sort by created_at, and reverse so it's the right way round
    all_forming.sort_by_key(|&g| &g.created_at);
    all_forming = all_forming.into_iter().rev().collect();

    if all_forming.is_empty() {
        ui.label("No forming games found.");
    } else {
        for game in all_forming {
            egui::Frame::none()
                .fill(egui::Color32::BLACK)
                .rounding(4.)
                .outer_margin(4.)
                .inner_margin(4.)
                .show(ui, |ui| {
                    ui.horizontal(|ui| {
                        ui.label(format!(
                            "Host: {}",
                            global
                                .users_cache
                                .get(&game.host_id)
                                .unwrap_or(&UserPub {
                                    id: "".to_string(),
                                    created_at: "".to_string(),
                                    username: "".to_string()
                                })
                                .username
                        ));
                        ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
                            if game.guest_id.clone().unwrap_or_default() == cfg_user.id {
                                ui.add_enabled(false, egui::Button::new("Joined"));
                                if ui.button("Inspect").clicked() {
                                    global.cur_game = Some(game.clone());
                                    data.state = PlayScreenState::InLobbyGuest;
                                }
                            } else if game.host_id == cfg_user.id {
                                ui.add_enabled(false, egui::Button::new("Host"));
                                if ui.button("Inspect").clicked() {
                                    global.cur_game = Some(game.clone());
                                    data.state = PlayScreenState::InLobbyHost;
                                }
                            } else if ui.button("Join").clicked() {
                                //data.cur_game = Some(game.clone());
                                //joingame_ev_w.send(JoinGameEvent);
                            }
                        });
                    });
                });
        }
    }
}

fn browse_inprogress(
    ui: &mut egui::Ui,
    data: &mut PlayScreenData,
    global: &mut Global,
    cfg_user: &CfgUser,
) {
    if data.waiting_for_my_games {
        ui.horizontal(|ui| {
            ui.spinner();
            ui.label("loading...");
        });
        return;
    }

    let my_games_inprogress: Vec<&GamePub> = global
        .games_cache
        .values()
        .filter(|g| {
            g.state == GAMESTATE_INPROGRESS
                && (g.host_id == cfg_user.id
                    || g.guest_id.clone().unwrap_or("".to_string()) == cfg_user.id)
        })
        .collect();

    if my_games_inprogress.is_empty() {
        ui.label("No games found.");
    } else {
        for game in my_games_inprogress {
            egui::Frame::none()
                .fill(egui::Color32::BLACK)
                .rounding(4.)
                .outer_margin(4.)
                .inner_margin(4.)
                .show(ui, |ui| {
                    ui.horizontal(|ui| {
                        ui.label(format!(
                            "Host: {}",
                            global
                                .users_cache
                                .get(&game.host_id)
                                .unwrap_or(&UserPub {
                                    id: "".to_string(),
                                    created_at: "".to_string(),
                                    username: "N/A".to_string()
                                })
                                .username
                        ));
                        ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
                            if ui.button("Resume").clicked() {
                                global.cur_game = Some(game.clone());
                                //resumegame_ev_w.send(ResumeGameEvent);
                            }
                        });
                    });
                });
        }
    }
}

fn browse_finished(
    ui: &mut egui::Ui,
    data: &mut PlayScreenData,
    global: &Global,
    cfg_user: &CfgUser,
) {
    if data.waiting_for_my_games {
        ui.horizontal(|ui| {
            ui.spinner();
            ui.label("loading...");
        });
        return;
    }

    let my_games_finished: Vec<&GamePub> = global
        .games_cache
        .values()
        .filter(|g| {
            g.state == GAMESTATE_FINISHED
                && (g.host_id == cfg_user.id
                    || g.guest_id.clone().unwrap_or("".to_string()) == cfg_user.id)
        })
        .collect();

    if my_games_finished.is_empty() {
        ui.label("No games found.");
    } else {
        for game in my_games_finished {
            egui::Frame::none()
                .fill(egui::Color32::BLACK)
                .rounding(4.)
                .outer_margin(4.)
                .inner_margin(4.)
                .show(ui, |ui| {
                    ui.horizontal(|ui| {
                        ui.label(format!(
                            "Host: {}",
                            global
                                .users_cache
                                .get(&game.host_id)
                                .unwrap_or(&UserPub {
                                    id: "".to_string(),
                                    created_at: "".to_string(),
                                    username: "".to_string()
                                })
                                .username
                        ));
                    });
                });
        }
    }
}