use eframe::egui;

fn main() -> eframe::Result<()> {
    let options = eframe::NativeOptions{
        viewport: egui::ViewportBuilder::default()
            .with_fullscreen(true)
            .with_min_inner_size(egui::vec2(800.0, 600.0)) // Minimum width, height
            .with_inner_size(egui::vec2(7680.0, 4320.0)), // Initial size
        ..Default::default()
    };
    eframe::run_native(
    "Knightly",
    options,
    Box::new(|cc| {
        let mut fonts = egui::FontDefinitions::default();
        fonts.font_data.insert(
            "symbols".to_owned(),
            egui::FontData::from_static(include_bytes!("../fonts/DejaVuSans.ttf")).into(),
        );
        fonts
            .families
            .entry(egui::FontFamily::Proportional)
            .or_default()
            .insert(0, "symbols".to_owned());
        cc.egui_ctx.set_fonts(fonts);
        Ok(Box::new(ChessApp::default()))
    }),
)
}

#[derive(Clone, Copy, PartialEq, Debug)]
enum Piece {
    King(char),
    Queen(char),
    Rook(char),
    Bishop(char),
    Knight(char),
    Pawn(char),
    Empty,
}

impl Piece {
    fn symbol(&self) -> &'static str {
        match self {
            Piece::King('w') => "♔",
            Piece::Queen('w') => "♕",
            Piece::Rook('w') => "♖",
            Piece::Bishop('w') => "♗",
            Piece::Knight('w') => "♘",
            Piece::Pawn('w') => "♙",
            Piece::King('b') => "♚",
            Piece::Queen('b') => "♛",
            Piece::Rook('b') => "♜",
            Piece::Bishop('b') => "♝",
            Piece::Knight('b') => "♞",
            Piece::Pawn('b') => "♟︎",
            Piece::Empty => "",
            _ => "",
        }
    }
}

#[derive(PartialEq, Debug)]
enum Turn {
    White,
    Black,
}

enum AppState {
    MainMenu,
    InGame,
    Settings,
}

struct ChessApp {
    fullscreen: bool,
    resolutions: Vec<(u32, u32)>,
    selected_resolution: usize,
    state: AppState,
    board: [[Piece; 8]; 8],
    selected: Option<(usize, usize)>,
    turn: Turn,
    pending_settings: PendingSettings,
    server_port: String,
}

#[derive(Default)]
struct PendingSettings {
    fullscreen: bool,
    selected_resolution: usize,
    server_port: String,
}

impl Default for ChessApp {
    fn default() -> Self {
        Self {
            fullscreen: true,
            resolutions: vec![
                (1280, 720),
                (1600, 900),
                (1920, 1080),
                (2560, 1440),
                (3840, 2160),
                (7680, 4320),
            ],
            selected_resolution: 2, // Default to 1920x1080
            state: AppState::MainMenu,
            board: Self::starting_board(),
            selected: None,
            turn: Turn::White,
            pending_settings: PendingSettings::default(),
            server_port: "8080".to_string(), // Default port
        }
    }
}

impl ChessApp {
    fn starting_board() -> [[Piece; 8]; 8] {
        use Piece::*;
        [
            [
                Rook('b'),
                Knight('b'),
                Bishop('b'),
                Queen('b'),
                King('b'),
                Bishop('b'),
                Knight('b'),
                Rook('b'),
            ],
            [Pawn('b'); 8],
            [Empty; 8],
            [Empty; 8],
            [Empty; 8],
            [Empty; 8],
            [Pawn('w'); 8],
            [
                Rook('w'),
                Knight('w'),
                Bishop('w'),
                Queen('w'),
                King('w'),
                Bishop('w'),
                Knight('w'),
                Rook('w'),
            ],
        ]
    }

    fn handle_click(&mut self, row: usize, col: usize) {
        if let Some((r, c)) = self.selected {
            let piece = self.board[r][c];
            self.board[r][c] = Piece::Empty;
            self.board[row][col] = piece;
            self.selected = None;
            self.turn = if self.turn == Turn::White {
                Turn::Black
            } else {
                Turn::White
            };
        } else {
            if self.board[row][col] != Piece::Empty {
                self.selected = Some((row, col));
            }
        }
    }

    fn apply_settings(&mut self, ctx: &egui::Context) {
        self.fullscreen = self.pending_settings.fullscreen;
        self.selected_resolution = self.pending_settings.selected_resolution;
        self.server_port = self.pending_settings.server_port.clone();
        
        if let Some(resolution) = self.resolutions.get(self.selected_resolution) {
            ctx.send_viewport_cmd(egui::ViewportCommand::InnerSize(
                egui::Vec2::new(resolution.0 as f32, resolution.1 as f32)
            ));
        }
        
        ctx.send_viewport_cmd(egui::ViewportCommand::Fullscreen(self.fullscreen));
    }

    fn enter_settings(&mut self) {
        self.pending_settings.fullscreen = self.fullscreen;
        self.pending_settings.selected_resolution = self.selected_resolution;
        self.pending_settings.server_port = self.server_port.clone();
        self.state = AppState::Settings;
    }
}

impl eframe::App for ChessApp {
    fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) {
        match self.state {
            AppState::MainMenu => {
                egui::CentralPanel::default().show(ctx, |ui| {
                    ui.vertical_centered(|ui| {
                        ui.heading("♞ Knightly ♞");
                        ui.add_space(30.0);

                        if ui.add_sized([300.0, 60.0], egui::Button::new("Play")).clicked() {
                            self.state = AppState::InGame;
                        }
                        ui.add_space(8.0);
                        
                        if ui.add_sized([300.0, 60.0], egui::Button::new("Settings")).clicked() {
                            self.enter_settings();
                        }
                        ui.add_space(8.0);
                        
                        if ui
                            .add_sized([300.0, 60.0], egui::Button::new("Quit"))
                            .clicked()
                        {
                            std::process::exit(0);
                        }
                    });
                });
            }

            AppState::Settings => {
                egui::CentralPanel::default().show(ctx, |ui| {
                    ui.vertical_centered(|ui| {
                        ui.heading("Settings");
                        ui.add_space(30.0);

                        // Fullscreen toggle
                        ui.horizontal(|ui| {
                            ui.label("Fullscreen:");
                            if ui.checkbox(&mut self.pending_settings.fullscreen, "").changed() {
                                // If enabling fullscreen, we might want to disable resolution selection
                            }
                        });
                        ui.add_space(10.0);

                        // Resolution dropdown
                        ui.horizontal(|ui| {
                            ui.label("Resolution:");
                            egui::ComboBox::new("resolution_combo", "")
                                .selected_text(format!(
                                    "{}x{}",
                                    self.resolutions[self.pending_settings.selected_resolution].0,
                                    self.resolutions[self.pending_settings.selected_resolution].1
                                ))
                                .show_ui(ui, |ui| {
                                    for (i, &(width, height)) in self.resolutions.iter().enumerate() {
                                        ui.selectable_value(
                                            &mut self.pending_settings.selected_resolution,
                                            i,
                                            format!("{}x{}", width, height),
                                        );
                                    }
                                });
                        });
                        ui.add_space(10.0);

                        // Server port input field
                        ui.horizontal(|ui| {
                            ui.label("Local Server Port:");
                            ui.add(egui::TextEdit::singleline(&mut self.pending_settings.server_port)
                                .desired_width(100.0)
                                .hint_text("8080"));
                        });
                        ui.add_space(30.0);

                        // Apply and Cancel buttons
                        ui.horizontal(|ui| {
                            if ui.add_sized([140.0, 40.0], egui::Button::new("Apply")).clicked() {
                                self.apply_settings(ctx);
                                self.state = AppState::MainMenu;
                            }
                            
                            if ui.add_sized([140.0, 40.0], egui::Button::new("Cancel")).clicked() {
                                self.state = AppState::MainMenu;
                            }
                        });
                    });
                });
            }

            AppState::InGame => {
                egui::TopBottomPanel::top("menu_bar").show(ctx, |ui| {
                    ui.horizontal(|ui| {
                        if ui.button("Main Menu").clicked() {
                            self.state = AppState::MainMenu;
                        }
                        if ui.button("Settings").clicked() {
                            self.enter_settings();
                        }
                        if ui.button("New Game").clicked() {
                            *self = ChessApp::default();
                            self.state = AppState::InGame;
                        }
                        ui.separator();
                        ui.label(format!("Turn: {:?}", self.turn));
                    });
                });
                
                egui::CentralPanel::default().show(ctx, |ui| {
                    ui.vertical_centered(|ui| {
                        let full_avail = ui.available_rect_before_wrap();
                        let board_tile = (full_avail.width().min(full_avail.height())) / 8.0;
                        let board_size = board_tile * 8.0;
                        
                        // Create a child UI at the board position
                        let (response, painter) = ui.allocate_painter(
                            egui::Vec2::new(board_size, board_size),
                            egui::Sense::click()
                        );
                        
                        let board_rect = egui::Rect::from_center_size(
                            full_avail.center(),
                            egui::vec2(board_size, board_size)
                        );
                        
                        // Draw the chess board
                        let tile_size = board_size / 8.0;
                        for row in 0..8 {
                            for col in 0..8 {
                                let color = if (row + col) % 2 == 0 {
                                    egui::Color32::from_rgb(100, 97, 97)
                                } else {
                                    egui::Color32::from_rgb(217, 217, 217)
                                };
                                
                                let rect = egui::Rect::from_min_size(
                                    egui::Pos2::new(
                                        board_rect.min.x + col as f32 * tile_size,
                                        board_rect.min.y + row as f32 * tile_size
                                    ),
                                    egui::Vec2::new(tile_size, tile_size)
                                );
                                
                                painter.rect_filled(rect, 0.0, color);
                                
                                // Draw piece
                                let piece = self.board[row][col];
                                if piece != Piece::Empty {
                                    let symbol = piece.symbol();
                                    let font_id = egui::FontId::proportional(tile_size * 0.75);
                                    painter.text(
                                        rect.center(),
                                        egui::Align2::CENTER_CENTER,
                                        symbol,
                                        font_id,
                                        if matches!(piece, Piece::King('w') | Piece::Queen('w') | Piece::Rook('w') | Piece::Bishop('w') | Piece::Knight('w') | Piece::Pawn('w')) {
                                            egui::Color32::WHITE
                                        } else {
                                            egui::Color32::BLACK
                                        }
                                    );
                                }
                                
                                // Draw selection highlight
                                if self.selected == Some((row, col)) {
                                    painter.rect_stroke(
                                        rect, 
                                        0.0, 
                                        egui::Stroke::new(3.0, egui::Color32::RED),
                                        egui::StrokeKind::Inside
                                    );
                                }
                                
                                // Handle clicks
                                if ui.ctx().input(|i| i.pointer.primary_clicked()) {
                                    let click_pos = ui.ctx().input(|i| i.pointer.interact_pos()).unwrap();
                                    if rect.contains(click_pos) {
                                        self.handle_click(row, col);
                                    }
                                }
                            }
                        }
                    });
                });
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_initial_board_setup() {
        let app = ChessApp::default();
        assert!(matches!(app.board[0][0], Piece::Rook('b')));
        assert!(matches!(app.board[7][0], Piece::Rook('w')));

        assert!(matches!(app.board[1][0], Piece::Pawn('b')));
        assert!(matches!(app.board[6][0], Piece::Pawn('w')));
    }
    
    #[test]
    fn test_piece_symbols() {
        assert_eq!(Piece::King('w').symbol(), "♔");
        assert_eq!(Piece::King('b').symbol(), "♚");
        assert_eq!(Piece::Empty.symbol(), "");
    }
    
    #[test]
    fn test_piece_selection() {
        let mut app = ChessApp::default();
        app.handle_click(6, 0);
        assert_eq!(app.selected, Some((6, 0)));
        app.handle_click(6, 0);
        assert_eq!(app.selected, None);
    }
    
    #[test]
    fn test_piece_movement() {
        let mut app = ChessApp::default();
        // Select and move a piece
        app.handle_click(6, 0); // Select white pawn
        app.handle_click(5, 0); // Move to empty square
        assert_eq!(app.board[6][0], Piece::Empty);
        assert!(matches!(app.board[5][0], Piece::Pawn('w')));
    }

    #[test]
    fn test_turn_switching() {
        let mut app = ChessApp::default();
        assert_eq!(app.turn, Turn::White);
        app.handle_click(6, 0); // White selects
        app.handle_click(5, 0); // White moves
        assert_eq!(app.turn, Turn::Black); // Should now be Black's turn
    }
    
    #[test]
    fn test_server_port_default() {
        let app = ChessApp::default();
        assert_eq!(app.server_port, "8080");
    }
}
