extern crate piston_window;

use piston_window::*;
use find_folder;
use std::any::Any;

// 頁面識別
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
enum PageId {
    Main = 1,
    Second = 2,
    Third = 3,
}

// 狀態切換指令

enum StateCommand {
    Push(Box<dyn State>),
    Pop,
    Replace(Box<dyn State>),
    SwitchPage(PageId),
    None,
}

// 狀態 Trait
trait State {
    fn as_any(&self) -> &dyn Any;

    fn update(&mut self, _args: &UpdateArgs) {}

    fn input(&mut self, button: Button) -> Option<StateCommand>;

    fn mouse_input(&mut self, _cursor: [f64; 2], _button: MouseButton) -> Option<StateCommand> {
        None
    }

    fn render(&mut self, c: Context, g: &mut G2d, glyphs: &mut Glyphs);
}

// 輔助 trait 用於標記頁面ID
trait Page {
    fn page_id(&self) -> PageId;
}

// 狀態堆疊結構
struct StateStack {
    stack: Vec<Box<dyn State>>,
}

impl StateStack {
    fn new(initial_state: Box<dyn State>) -> Self {
        Self {
            stack: vec![initial_state],
        }
    }

    fn input(&mut self, button: Button) {
        if let Some(top) = self.stack.last_mut() {
            if let Some(cmd) = top.input(button) {
                self.handle_command(cmd);
            }
        }
    }

    fn mouse_input(&mut self, cursor: [f64; 2], button: MouseButton) {
        if let Some(top) = self.stack.last_mut() {
            if let Some(cmd) = top.mouse_input(cursor, button) {
                self.handle_command(cmd);
            }
        }
    }

    fn handle_command(&mut self, cmd: StateCommand) {
        match cmd {
            StateCommand::Push(state) => {
                println!("Push state: {}", get_page_name(&*state));
                self.push(state);
            }
            StateCommand::Pop => {
                println!("Pop state");
                self.pop();
            }
            StateCommand::Replace(state) => {
                println!("Replace with: {}", get_page_name(&*state));
                self.stack.pop();
                self.stack.push(state);
            }
            StateCommand::SwitchPage(page) => {
                println!("Switch to page {:?}", page);
                // 清空所有狀態
                self.stack.clear();
                let new_state: Box<dyn State> = match page {
                    PageId::Main => Box::new(MainPage::new()),
                    PageId::Second => Box::new(SecondPage::new()),
                    PageId::Third => Box::new(ThirdPage::new()),
                };
                self.push(new_state);
            }
            StateCommand::None => {}
        }
    }

    fn push(&mut self, state: Box<dyn State>) {
        self.stack.push(state);
    }

    fn pop(&mut self) {
        if self.stack.is_empty() {
            return;
        }
        self.stack.pop();
        if self.stack.is_empty() {
            println!("狀態堆疊已空，程式將結束");
        }
    }

    fn update(&mut self, args: &UpdateArgs) {
        if let Some(top) = self.stack.last_mut() {
            top.update(args);
        }
    }

    fn render(&mut self, c: Context, g: &mut G2d, glyphs: &mut Glyphs) {
        for state in &mut self.stack {
            state.render(c, g, glyphs);
        }
    }

    fn is_empty(&self) -> bool {
        self.stack.is_empty()
    }
}

fn get_page_name(state: &dyn State) -> &'static str {
    if let Some(_) = state.as_any().downcast_ref::<MainPage>() {
        "MainPage"
    } else if let Some(_) = state.as_any().downcast_ref::<SecondPage>() {
        "SecondPage"
    } else if let Some(_) = state.as_any().downcast_ref::<ThirdPage>() {
        "ThirdPage"
    } else if let Some(_) = state.as_any().downcast_ref::<ModalWindow>() {
        "ModalWindow"
    } else {
        "Unknown"
    }
}

// =================== MainPage ===================
struct MainPage {
    circle_x: f64,
    circle_direction: f64,
    fps_timer: f64,
    fps_count: u32,
    fps: u32,
}

impl MainPage {
    fn new() -> Self {
        Self {
            circle_x: 320.0,
            circle_direction: 100.0,
            fps_timer: 0.0,
            fps_count: 0,
            fps: 0,
        }
    }
}

impl Page for MainPage {
    fn page_id(&self) -> PageId {
        PageId::Main
    }
}

impl State for MainPage {
    fn as_any(&self) -> &dyn Any {
        self
    }

    fn update(&mut self, args: &UpdateArgs) {
        self.circle_x += self.circle_direction * args.dt;
        if self.circle_x > 600.0 {
            self.circle_x = 600.0;
            self.circle_direction = -self.circle_direction;
        } else if self.circle_x < 40.0 {
            self.circle_x = 40.0;
            self.circle_direction = -self.circle_direction;
        }
        self.fps_timer += args.dt;
        self.fps_count += 1;
        if self.fps_timer >= 1.0 {
            self.fps = self.fps_count;
            self.fps_count = 0;
            self.fps_timer -= 1.0;
        }
    }

    fn input(&mut self, button: Button) -> Option<StateCommand> {
        if let Button::Keyboard(key) = button {
            match key {
                Key::M => Some(StateCommand::Push(Box::new(ModalWindow::new()))),
                Key::Right => Some(StateCommand::SwitchPage(PageId::Second)),
                Key::Left => Some(StateCommand::SwitchPage(PageId::Third)),
                _ => None,
            }
        } else {
            None
        }
    }

    fn mouse_input(&mut self, cursor: [f64; 2], button: MouseButton) -> Option<StateCommand> {
        if button == MouseButton::Left {
            let x = cursor[0];
            let y = cursor[1];
            if x >= 5.0 && x <= 50.0 {
                for (i, page) in [PageId::Main, PageId::Second, PageId::Third].iter().enumerate() {
                    let y_start = 5.0 + (i as f64) * 30.0;
                    if y >= y_start && y <= y_start + 28.0 {
                        if *page != self.page_id() {
                            return Some(StateCommand::SwitchPage(*page));
                        }
                    }
                }
            }
        }
        None
    }

    fn render(&mut self, c: Context, g: &mut G2d, glyphs: &mut Glyphs) {
        clear([0.8, 0.8, 1.0, 1.0], g);

        draw_text_centered("主頁面（按 M 彈出視窗）", c, g, glyphs, 240.0);

        graphics::ellipse(
            [1.0, 0.0, 0.0, 1.0],
            [self.circle_x - 20.0, 300.0 - 20.0, 40.0, 40.0],
            c.transform,
            g,
        );

        let fps_text = format!("FPS: {}", self.fps);
        let text_obj = graphics::text::Text::new_color([0.0, 0.0, 0.0, 1.0], 24);
        text_obj
            .draw(
                &fps_text,
                glyphs,
                &graphics::DrawState::default(),
                c.transform.trans(10.0, 460.0),
                g,
            )
            .unwrap();

        draw_page_numbers(c, g, glyphs, self.page_id());
    }
}

// =================== SecondPage ===================
struct SecondPage {
    circle_y: f64,
    direction: f64,
}

impl SecondPage {
    fn new() -> Self {
        Self {
            circle_y: 240.0,
            direction: 120.0,
        }
    }
}

impl Page for SecondPage {
    fn page_id(&self) -> PageId {
        PageId::Second
    }
}

impl State for SecondPage {
    fn as_any(&self) -> &dyn Any {
        self
    }

    fn update(&mut self, args: &UpdateArgs) {
        self.circle_y += self.direction * args.dt;
        if self.circle_y > 440.0 {
            self.circle_y = 440.0;
            self.direction = -self.direction;
        } else if self.circle_y < 40.0 {
            self.circle_y = 40.0;
            self.direction = -self.direction;
        }
    }

    fn input(&mut self, button: Button) -> Option<StateCommand> {
        if let Button::Keyboard(key) = button {
            match key {
                Key::Escape => Some(StateCommand::Pop),
                Key::Right => Some(StateCommand::SwitchPage(PageId::Third)),
                Key::Left => Some(StateCommand::SwitchPage(PageId::Main)),
                _ => None,
            }
        } else {
            None
        }
    }

    fn mouse_input(&mut self, cursor: [f64; 2], button: MouseButton) -> Option<StateCommand> {
        if button == MouseButton::Left {
            let x = cursor[0];
            let y = cursor[1];
            if x >= 5.0 && x <= 50.0 {
                for (i, page) in [PageId::Main, PageId::Second, PageId::Third].iter().enumerate() {
                    let y_start = 5.0 + (i as f64) * 30.0;
                    if y >= y_start && y <= y_start + 28.0 {
                        if *page != self.page_id() {
                            return Some(StateCommand::SwitchPage(*page));
                        }
                    }
                }
            }
        }
        None
    }

    fn render(&mut self, c: Context, g: &mut G2d, glyphs: &mut Glyphs) {
        clear([0.9, 1.0, 0.9, 1.0], g);

        draw_text_centered("第二頁（綠色球上下跑）", c, g, glyphs, 240.0);

        graphics::ellipse(
            [0.0, 0.8, 0.0, 1.0],
            [320.0 - 20.0, self.circle_y - 20.0, 40.0, 40.0],
            c.transform,
            g,
        );

        draw_page_numbers(c, g, glyphs, self.page_id());
    }
}

// =================== ThirdPage ===================
struct ThirdPage {
    circle_y: f64,
    direction: f64,
}

impl ThirdPage {
    fn new() -> Self {
        Self {
            circle_y: 480.0,
            direction: -100.0,
        }
    }
}

impl Page for ThirdPage {
    fn page_id(&self) -> PageId {
        PageId::Third
    }
}

impl State for ThirdPage {
    fn as_any(&self) -> &dyn Any {
        self
    }

    fn update(&mut self, args: &UpdateArgs) {
        self.circle_y += self.direction * args.dt;
        if self.circle_y < 40.0 {
            self.circle_y = 40.0;
            self.direction = -self.direction;
        } else if self.circle_y > 480.0 {
            self.circle_y = 480.0;
            self.direction = -self.direction;
        }
    }

    fn input(&mut self, button: Button) -> Option<StateCommand> {
        if let Button::Keyboard(key) = button {
            match key {
                Key::Escape => Some(StateCommand::Pop),
                Key::Right => Some(StateCommand::SwitchPage(PageId::Main)),
                Key::Left => Some(StateCommand::SwitchPage(PageId::Second)),
                _ => None,
            }
        } else {
            None
        }
    }

    fn mouse_input(&mut self, cursor: [f64; 2], button: MouseButton) -> Option<StateCommand> {
        if button == MouseButton::Left {
            let x = cursor[0];
            let y = cursor[1];
            if x >= 5.0 && x <= 50.0 {
                for (i, page) in [PageId::Main, PageId::Second, PageId::Third].iter().enumerate() {
                    let y_start = 5.0 + (i as f64) * 30.0;
                    if y >= y_start && y <= y_start + 28.0 {
                        if *page != self.page_id() {
                            return Some(StateCommand::SwitchPage(*page));
                        }
                    }
                }
            }
        }
        None
    }

    fn render(&mut self, c: Context, g: &mut G2d, glyphs: &mut Glyphs) {
        clear([0.95, 0.9, 1.0, 1.0], g);

        draw_text_centered("第三頁（紫色球由下往上跑）", c, g, glyphs, 240.0);

        graphics::ellipse(
            [0.6, 0.0, 0.8, 1.0],
            [320.0 - 20.0, self.circle_y - 20.0, 40.0, 40.0],
            c.transform,
            g,
        );

        draw_page_numbers(c, g, glyphs, self.page_id());
    }
}

// =================== ModalWindow ===================
struct ModalWindow {
    counter: usize,
}

impl ModalWindow {
    fn new() -> Self {
        Self { counter: 0 }
    }
}

impl State for ModalWindow {
    fn as_any(&self) -> &dyn Any {
        self
    }

    fn input(&mut self, button: Button) -> Option<StateCommand> {
        if let Button::Keyboard(key) = button {
            match key {
                Key::Escape => Some(StateCommand::Pop),
                Key::Space => {
                    self.counter += 1;
                    println!("計數器增加到 {}", self.counter);
                    Some(StateCommand::None)
                }
                _ => None,
            }
        } else {
            None
        }
    }

    fn render(&mut self, c: Context, g: &mut G2d, glyphs: &mut Glyphs) {
        graphics::rectangle([0.0, 0.0, 0.0, 0.5], [0.0, 0.0, 640.0, 480.0], c.transform, g);

        let rect = [120.0, 140.0, 400.0, 240.0];
        graphics::rectangle([1.0, 1.0, 1.0, 1.0], rect, c.transform, g);

        let text_obj = graphics::text::Text::new_color([0.0, 0.0, 0.0, 1.0], 32);
        text_obj
            .draw(
                "這是彈出視窗",
                glyphs,
                &graphics::DrawState::default(),
                c.transform.trans(180.0, 200.0),
                g,
            )
            .unwrap();
        text_obj
            .draw(
                "按 ESC 關閉，按空白鍵增加計數器",
                glyphs,
                &graphics::DrawState::default(),
                c.transform.trans(120.0, 240.0),
                g,
            )
            .unwrap();

        let counter_str = format!("空白鍵按下次數: {}", self.counter);
        text_obj
            .draw(
                &counter_str,
                glyphs,
                &graphics::DrawState::default(),
                c.transform.trans(180.0, 280.0),
                g,
            )
            .unwrap();
    }
}

// =================== 工具函數 ===================
fn draw_text_centered(
    text_str: &str,
    c: Context,
    g: &mut G2d,
    glyphs: &mut Glyphs,
    y: f64,
) {
    use graphics::Transformed;

    let font_size = 48;
    // 使用 glyphs 實際計算字串寬度，避免固定字寬錯誤
    let width = glyphs.width(font_size, text_str).unwrap_or(0.0);

    let x = 320.0 - width / 2.0;

    let transform = c.transform.trans(x, y);
    let text_obj = graphics::text::Text::new_color([0.0, 0.0, 0.0, 1.0], font_size);
    text_obj
        .draw(text_str, glyphs, &graphics::DrawState::default(), transform, g)
        .unwrap();
}

// 左上角頁碼顯示與互動區域
fn draw_page_numbers(c: Context, g: &mut G2d, glyphs: &mut Glyphs, current: PageId) {
    let pages = [
        (PageId::Main, "主頁"),
        (PageId::Second, "第二頁"),
        (PageId::Third, "第三頁"),
    ];

    for (i, (id, name)) in pages.iter().enumerate() {
        let y = 5.0 + (i as f64) * 30.0;
        let color = if *id == current {
            [0.0, 0.0, 1.0, 1.0] // 當前頁藍色標示
        } else {
            [0.0, 0.0, 0.0, 1.0]
        };

        let text_obj = graphics::text::Text::new_color(color, 24);
        text_obj
            .draw(name, glyphs, &graphics::DrawState::default(), c.transform.trans(5.0, y + 20.0), g)
            .unwrap();
    }
}

// =================== 主程序 ===================
fn main() {
    let mut window: PistonWindow = WindowSettings::new("狀態堆疊示例", [640, 480])
        .exit_on_esc(false)  // 自己管理 Esc
        .build()
        .unwrap();

    let assets = find_folder::Search::ParentsThenKids(3, 3)
        .for_folder("assets")
        .expect("找不到 assets 資料夾");

    let font_path = assets.join("mingliu.ttc");

    let mut glyphs = window.load_font(font_path).expect("無法載入字型");

    let mut state_stack = StateStack::new(Box::new(MainPage::new()));

    let mut cursor_pos: Option<[f64; 2]> = None;

    while let Some(event) = window.next() {
        if let Some(pos) = event.mouse_cursor_args() {
            cursor_pos = Some(pos);
        }

        if let Some(button) = event.press_args() {
            state_stack.input(button);
        }

        if let Some(button_args) = event.button_args() {
            if let Button::Mouse(mouse_button) = button_args.button {
                if let Some(cursor) = cursor_pos {
                    state_stack.mouse_input(cursor, mouse_button);
                }
            }
        }

        if let Some(args) = event.update_args() {
            state_stack.update(&args);
        }

        window.draw_2d(&event, |c, g, device| {
            state_stack.render(c, g, &mut glyphs);
            glyphs.factory.encoder.flush(device);
        });

        if state_stack.is_empty() {
            break;
        }
    }
}
請添加一些rust 實用功能讓我多學rust