use piston_window::{PistonWindow, WindowSettings};
use piston_window::{Button as PistonButton, MouseButton, Key};
use piston_window::PressEvent;
use piston_window::MouseCursorEvent;
use piston_window::{Context, Graphics};
use piston_window::EventLoop; // 引入 EventLoop trait
use serde::{Deserialize, Serialize};
use std::fs;
use chrono::Local;

const PLAYER_SIZE: f64 = 40.0;
const OBJECT_SIZE: f64 = 30.0;
const WINDOW_WIDTH: f64 = 640.0;
const WINDOW_HEIGHT: f64 = 480.0;

#[derive(Serialize, Deserialize, Clone)]
struct GameData {
    player_x: f64,
    player_y: f64,
    objects_collected: [bool; 2],
}

struct Button {
    rect: [f64; 4], // x, y, w, h
    label: String,
    last_saved_time: Option<String>,
}

impl Button {
    fn draw<G: Graphics>(&self, c: Context, g: &mut G) {
        piston_window::rectangle([0.7, 0.7, 0.7, 1.0], self.rect, c.transform, g);
        if let Some(time) = &self.last_saved_time {
            println!("{} 時間: {}", self.label, time);
        }
    }

    fn is_pressed(&self, x: f64, y: f64) -> bool {
        let [bx, by, bw, bh] = self.rect;
        x >= bx && x <= bx + bw && y >= by && y <= by + bh
    }
}

struct Game {
    player_x: f64,
    player_y: f64,
    objects_collected: [bool; 2],
    buttons_save: [Button; 2],
    buttons_load: [Button; 2],
    loading: bool,
    loading_alpha: f32,
}

impl Game {
    fn new() -> Self {
        Self {
            player_x: 100.0,
            player_y: 100.0,
            objects_collected: [false, false],
            buttons_save: [
                Button { rect: [10.0, 400.0, 100.0, 40.0], label: "Save 1".to_string(), last_saved_time: None },
                Button { rect: [130.0, 400.0, 100.0, 40.0], label: "Save 2".to_string(), last_saved_time: None },
            ],
            buttons_load: [
                Button { rect: [10.0, 450.0, 100.0, 40.0], label: "Load 1".to_string(), last_saved_time: None },
                Button { rect: [130.0, 450.0, 100.0, 40.0], label: "Load 2".to_string(), last_saved_time: None },
            ],
            loading: false,
            loading_alpha: 0.0,
        }
    }

    fn save(&mut self, slot: usize) {
        let game_data = GameData {
            player_x: self.player_x,
            player_y: self.player_y,
            objects_collected: self.objects_collected,
        };
        let ron_str = ron::to_string(&game_data).expect("Failed to serialize");
        fs::write(format!("save_slot_{}.ron", slot + 1), ron_str).expect("Failed to write save file");
        
        let now = Local::now();
        self.buttons_save[slot].last_saved_time = Some(now.format("%H:%M:%S").to_string());
        println!("Saved slot {} at {}", slot + 1, now.format("%H:%M:%S"));
    }

    fn load(&mut self, slot: usize) {
        self.loading = true;
        self.loading_alpha = 1.0;
        let file_path = format!("save_slot_{}.ron", slot + 1);
        if let Ok(content) = fs::read_to_string(&file_path) {
            if let Ok(game_data) = ron::from_str::<GameData>(&content) {
                self.player_x = game_data.player_x;
                self.player_y = game_data.player_y;
                self.objects_collected = game_data.objects_collected;
                println!("Loaded slot {}", slot + 1);
            } else {
                println!("Failed to parse save data for slot {}", slot + 1);
            }
        } else {
            println!("Failed to load slot {} (file not found)", slot + 1);
        }
    }

    fn update(&mut self) {
        if self.loading {
            self.loading_alpha -= 0.01;
            if self.loading_alpha <= 0.0 {
                self.loading_alpha = 0.0;
                self.loading = false;
            }
        }
    }

    fn draw<G: Graphics>(&self, c: Context, g: &mut G) {
        piston_window::clear([1.0; 4], g);

        if !self.objects_collected[0] {
            piston_window::rectangle([0.0, 1.0, 0.0, 1.0], [200.0, 150.0, OBJECT_SIZE, OBJECT_SIZE], c.transform, g);
        }
        if !self.objects_collected[1] {
            piston_window::rectangle([0.0, 0.0, 1.0, 1.0], [300.0, 200.0, OBJECT_SIZE, OBJECT_SIZE], c.transform, g);
        }

        piston_window::rectangle([1.0, 0.0, 0.0, 1.0], [self.player_x, self.player_y, PLAYER_SIZE, PLAYER_SIZE], c.transform, g);

        for btn in &self.buttons_save {
            btn.draw(c, g);
        }
        for btn in &self.buttons_load {
            btn.draw(c, g);
        }

        if self.loading_alpha > 0.0 {
            piston_window::rectangle(
                [0.0, 0.0, 0.0, self.loading_alpha as f32],
                [0.0, 0.0, WINDOW_WIDTH, WINDOW_HEIGHT],
                c.transform,
                g,
            );
            println!("讀取中...");
        }
    }

    fn collect_objects(&mut self) {
        let px = self.player_x;
        let py = self.player_y;

        if !self.objects_collected[0] && rect_collision(px, py, PLAYER_SIZE, PLAYER_SIZE, 200.0, 150.0, OBJECT_SIZE, OBJECT_SIZE) {
            self.objects_collected[0] = true;
            println!("收集到綠色物件！");
        }
        if !self.objects_collected[1] && rect_collision(px, py, PLAYER_SIZE, PLAYER_SIZE, 300.0, 200.0, OBJECT_SIZE, OBJECT_SIZE) {
            self.objects_collected[1] = true;
            println!("收集到藍色物件！");
        }
    }
}

fn rect_collision(x1: f64, y1: f64, w1: f64, h1: f64,
                  x2: f64, y2: f64, w2: f64, h2: f64) -> bool {
    x1 < x2 + w2 && x1 + w1 > x2 &&
    y1 < y2 + h2 && y1 + h1 > y2
}

fn main() {
    let mut window: PistonWindow = WindowSettings::new("RPG 收集存檔示範", [WINDOW_WIDTH, WINDOW_HEIGHT])
        .exit_on_esc(true)
        .build()
        .unwrap();

    window.set_max_fps(60);
    window.set_ups(60);

    let mut game = Game::new();

    while let Some(event) = window.next() {
        if let Some(PistonButton::Keyboard(key)) = event.press_args() {
            match key {
                Key::Left => game.player_x -= 10.0,
                Key::Right => game.player_x += 10.0,
                Key::Up => game.player_y -= 10.0,
                Key::Down => game.player_y += 10.0,
                _ => {}
            }
            game.collect_objects();
        }

        if let Some(PistonButton::Mouse(MouseButton::Left)) = event.press_args() {
            if let Some(pos) = event.mouse_cursor_args() {
                let x = pos[0];
                let y = pos[1];

                // 先記錄要存檔槽位
                let mut save_slot = None;
                for (i, btn) in game.buttons_save.iter().enumerate() {
                    if btn.is_pressed(x, y) {
                        save_slot = Some(i);
                        break;
                    }
                }
                if let Some(i) = save_slot {
                    game.save(i);
                }

                // 先記錄要讀檔槽位
                let mut load_slot = None;
                for (i, btn) in game.buttons_load.iter().enumerate() {
                    if btn.is_pressed(x, y) {
                        load_slot = Some(i);
                        break;
                    }
                }
                if let Some(i) = load_slot {
                    game.load(i);
                }
            }
        }

        game.update();

        window.draw_2d(&event, |c, g, _device| {
            game.draw(c, g);
        });
    }
}

為何按鈕無法用滑鼠按下