extern crate piston_window;


use piston_window::*;
use std::fs::OpenOptions;
use std::io::Write;
use std::fs;
use anyhow::Result;
use chrono::Local;


const FONT_PATH: &str = "./assets/mingliu.ttc";


// 主選單選項
const MAIN_MENU_ITEMS: &[&str] = &[
    "計算平方與平方和",    // 0
    "查看檔案內容",      // 1
    "看笑話文章",        // 2
    "離開程式",          // 3
];


// 笑話頁面選項
const JOKE_MENU_ITEMS: &[&str] = &[
    "返回主選單",
];


// 輸入頁面提示文字
const INPUT_PROMPT: &str = "請輸入正整數，按 Enter 確認，Esc 返回主選單";


// 簡單笑話文本
const JOKE_TEXT: &[&str] = &[
    "笑話：為什麼程式員喜歡海灘？",
    "因為有很多沙（stack）！",
    "笑話：為什麼Java程式員經常感冒？",
    "因為他們待在try-catch區塊裡。",
];


#[derive(PartialEq)]
enum Page {
    MainMenu,
    InputCalc,
    ShowFile,
    JokePage,
}


// 計算平方和並寫檔
fn calc_square_sum(num: i32, file_path: &str) -> Result<(String, i32)> {
    let squares: Vec<_> = (1..=num).map(|x| (x, x * x)).collect();
    let sum: i32 = squares.iter().map(|&(_, sq)| sq).sum();


    let mut record = format!("計算 {} 的平方:\n", num);
    for (val, sq) in &squares {
        record += &format!("{} 的平方是 {}\n", val, sq);
    }
    record += &format!("平方和為 {}\n計算時間：{}\n\n", sum, Local::now().format("%Y年%m月%d日 %H點%M分%S秒"));


    let mut file = OpenOptions::new()
        .append(true)
        .create(true)
        .open(file_path)?;


    writeln!(file, "{}", record)?;


    Ok((record, sum))
}


// 讀取檔案內容
fn read_file_contents(file_path: &str) -> Result<String> {
    match fs::read_to_string(file_path) {
        Ok(contents) => Ok(contents),
        Err(e) => Err(e.into()),
    }
}


// 將按鍵轉為數字字元
fn key_to_char(key: Key) -> Option<char> {
    match key {
        Key::D0 | Key::NumPad0 => Some('0'),
        Key::D1 | Key::NumPad1 => Some('1'),
        Key::D2 | Key::NumPad2 => Some('2'),
        Key::D3 | Key::NumPad3 => Some('3'),
        Key::D4 | Key::NumPad4 => Some('4'),
        Key::D5 | Key::NumPad5 => Some('5'),
        Key::D6 | Key::NumPad6 => Some('6'),
        Key::D7 | Key::NumPad7 => Some('7'),
        Key::D8 | Key::NumPad8 => Some('8'),
        Key::D9 | Key::NumPad9 => Some('9'),
        _ => None,
    }
}


fn main() {
    let mut window: PistonWindow = WindowSettings::new("多頁面選單 - Rust + Piston", [640, 480])
        .exit_on_esc(true)
        .build()
        .unwrap();


    let mut glyphs = window.load_font(FONT_PATH).expect("載入字型失敗");


    let mut page = Page::MainMenu;
    let mut selected_index = 0;


    // 輸入頁文字輸入緩存
    let mut input_buffer = String::new();


    // 檔案內容緩存
    let mut file_content = String::new();


    // 檔案內容頁面滾動偏移
    let mut scroll_offset: usize = 0;


    let log_file_path = "output.txt";


    while let Some(event) = window.next() {
        if let Some(Button::Mouse(MouseButton::Left)) = event.press_args() {
    match page {
        Page::MainMenu => {
            match selected_index {
                0 => {
                    page = Page::InputCalc;
                    input_buffer.clear();
                }
                1 => {
                    page = Page::ShowFile;
                    match read_file_contents(log_file_path) {
                        Ok(c) => file_content = c,
                        Err(_) => file_content = "讀取檔案失敗或無內容。".to_string(),
                    }
                    scroll_offset = 0;
                }
                2 => {
                    page = Page::JokePage;
                    selected_index = 0;
                }
                3 => {
                    // 離開程式
                    break;
                }
                _ => {}
            }
        }
        Page::JokePage => {
            // 唯一選項: 返回主選單
            if selected_index == 0 {
                page = Page::MainMenu;
                selected_index = 0;
            }
        }
        _ => {}
    }
}
        // 處理鍵盤事件
        if let Some(Button::Keyboard(key)) = event.press_args() {
            match page {
                Page::MainMenu => match key {
                    Key::Up => {
                        if selected_index > 0 {
                            selected_index -= 1;
                        }
                    }
                    Key::Down => {
                        if selected_index < MAIN_MENU_ITEMS.len() - 1 {
                            selected_index += 1;
                        }
                    }
                    Key::Return => {
                        match selected_index {
                            0 => {
                                page = Page::InputCalc;
                                input_buffer.clear();
                            }
                            1 => {
                                page = Page::ShowFile;
                                match read_file_contents(log_file_path) {
                                    Ok(c) => file_content = c,
                                    Err(_) => file_content = "讀取檔案失敗或無內容。".to_string(),
                                }
                                scroll_offset = 0;
                            }
                            2 => {
                                page = Page::JokePage;
                                selected_index = 0;
                            }
                            3 => break,
                            _ => {}
                        }
                    }
                    Key::Escape => break,
                    _ => {}
                },
                Page::InputCalc => match key {
                    Key::Return => {
                        if let Ok(num) = input_buffer.trim().parse::<i32>() {
                            if num > 0 {
                                match calc_square_sum(num, log_file_path) {
                                    Ok((_rec, sum)) => {
                                        println!("計算成功！平方和為 {}", sum);
                                    }
                                    Err(e) => {
                                        println!("計算錯誤: {}", e);
                                    }
                                }
                            } else {
                                println!("請輸入正整數！");
                            }
                        } else {
                            println!("輸入格式錯誤！");
                        }
                        page = Page::MainMenu;
                        selected_index = 0;
                    }
                    Key::Escape => {
                        page = Page::MainMenu;
                        selected_index = 0;
                    }
                    Key::Backspace => {
                        input_buffer.pop();
                    }
                    _ => {
                        if let Some(c) = key_to_char(key) {
                            input_buffer.push(c);
                        }
                    }
                },
                Page::ShowFile => match key {
                    Key::Escape | Key::Return => {
                        page = Page::MainMenu;
                        selected_index = 0;
                        scroll_offset = 0;
                    }
                    Key::Up => {
                        if scroll_offset > 0 {
                            scroll_offset -= 1;
                        }
                    }
                    Key::Down => {
                        scroll_offset += 1;
                    }
                    _ => {}
                },
                Page::JokePage => match key {
                    Key::Escape | Key::Return => {
                        page = Page::MainMenu;
                        selected_index = 0;
                    }
                    Key::Up => {
                        if selected_index > 0 {
                            selected_index -= 1;
                        }
                    }
                    Key::Down => {
                        if selected_index < JOKE_MENU_ITEMS.len() - 1 {
                            selected_index += 1;
                        }
                    }
                    _ => {}
                },
            }
        }


        // 處理滑鼠懸停選項 (同之前)
        if let Some(pos) = event.mouse_cursor_args() {
            let y = pos[1];
            let hover_index = match page {
                Page::MainMenu => {
                    if y < 150.0 {
                        None
                    } else {
                        let idx = ((y - 150.0) / 40.0) as usize;
                        if idx < MAIN_MENU_ITEMS.len() {
                            Some(idx)
                        } else {
                            None
                        }
                    }
                }
                Page::JokePage => {
                    if y < 350.0 {
                        None
                    } else {
                        let idx = ((y - 350.0) / 40.0) as usize;
                        if idx < JOKE_MENU_ITEMS.len() {
                            Some(idx)
                        } else {
                            None
                        }
                    }
                }
                Page::InputCalc | Page::ShowFile => None,
            };
            if let Some(i) = hover_index {
                selected_index = i;
            }
        }


        // 處理滑鼠滾輪 (檔案滾動頁面)
        if let Some(mouse_scroll) = event.mouse_scroll_args() {
            if page == Page::ShowFile {
                if mouse_scroll[1] > 0.0 {
                    if scroll_offset > 0 {
                        scroll_offset -= 1;
                    }
                } else if mouse_scroll[1] < 0.0 {
                    scroll_offset += 1;
                }
            }
        }


        let window_size = window.size();


        window.draw_2d(&event, |context, graphics, device| {
            clear([0., 0., 0., 1.], graphics);


            let title = match page {
                Page::MainMenu => "歡迎使用程式 - 主選單",
                Page::InputCalc => "計算平方與平方和",
                Page::ShowFile => "檔案內容",
                Page::JokePage => "笑話文章",
            };


            text::Text::new_color([1.0, 1.0, 1.0, 1.0], 36)
                .draw(title, &mut glyphs, &context.draw_state,
                      context.transform.trans(180.0, 80.0), graphics)
                .unwrap();


            match page {
                Page::MainMenu => {
                    let subtitle = "請用上下鍵與滑鼠選擇，Enter 確認，Esc 離開";
                    text::Text::new_color([0.7, 0.7, 0.7, 1.0], 18)
                        .draw(subtitle, &mut glyphs, &context.draw_state,
                              context.transform.trans(120.0, 110.0), graphics)
                        .unwrap();


                    for (i, item) in MAIN_MENU_ITEMS.iter().enumerate() {
                        let color = if i == selected_index {
                            [1.0, 1.0, 1.0, 1.0]
                        } else {
                            [0.6, 0.6, 0.6, 1.0]
                        };
                        let y = 150.0 + i as f64 * 40.0;
                        text::Text::new_color(color, 24)
                            .draw(item, &mut glyphs, &context.draw_state,
                                  context.transform.trans(150.0, y), graphics)
                            .unwrap();
                    }
                }
                Page::InputCalc => {
                    text::Text::new_color([0.6, 0.6, 0.6, 1.0], 20)
                        .draw(INPUT_PROMPT, &mut glyphs, &context.draw_state,
                              context.transform.trans(50.0, 150.0), graphics)
                        .unwrap();


                    // 顯示輸入內容
                    let input_display = format!("輸入: {}", input_buffer);
                    text::Text::new_color([1.0, 1.0, 1.0, 1.0], 24)
                        .draw(&input_display, &mut glyphs, &context.draw_state,
                              context.transform.trans(50.0, 200.0), graphics)
                        .unwrap();
                }
                Page::ShowFile => {
                    let lines: Vec<_> = file_content.lines().collect();
                    let max_lines = 20;
                    // 限制捲動範圍
                    if lines.len() > max_lines {
                        if scroll_offset > lines.len() - max_lines {
                            scroll_offset = lines.len() - max_lines;
                        }
                    } else {
                        scroll_offset = 0;
                    }


                    for (i, line) in lines.iter().skip(scroll_offset).take(max_lines).enumerate() {
                        let y = 150.0 + i as f64 * 20.0;
                        text::Text::new_color([0.8, 0.8, 0.8, 1.0], 18)
                            .draw(line, &mut glyphs, &context.draw_state,
                                  context.transform.trans(50.0, y), graphics)
                            .unwrap();
                    }
                }
                Page::JokePage => {
                    for (i, line) in JOKE_TEXT.iter().enumerate() {
                        let y = 150.0 + i as f64 * 30.0;
                        text::Text::new_color([0.9, 0.9, 0.1, 1.0], 20)
                            .draw(line, &mut glyphs, &context.draw_state,
                                  context.transform.trans(50.0, y), graphics)
                            .unwrap();
                    }
                    for (i, item) in JOKE_MENU_ITEMS.iter().enumerate() {
                        let color = if i == selected_index {
                            [1.0, 1.0, 1.0, 1.0]
                        } else {
                            [0.6, 0.6, 0.6, 1.0]
                        };
                        let y = 350.0 + i as f64 * 40.0;
                        text::Text::new_color(color, 24)
                            .draw(item, &mut glyphs, &context.draw_state,
                                  context.transform.trans(300.0, y), graphics)
                            .unwrap();
                    }
                }
            }


            glyphs.factory.encoder.flush(device);
        });
    }
}

有必要加入狀態機嗎