use roast2d::prelude::*;
use std::fs;
use std::sync::{Arc, Mutex};

struct CjkState {
    input: String,
}

impl Default for CjkState {
    fn default() -> Self {
        Self {
            input: "你好，世界！在这里输入中文……".to_string(),
        }
    }
}

struct CjkDemo {
    state: Arc<Mutex<CjkState>>,
}

impl Default for CjkDemo {
    fn default() -> Self {
        Self {
            state: Arc::new(Mutex::new(CjkState::default())),
        }
    }
}

fn load_system_cjk_font() -> Option<Vec<u8>> {
    #[cfg(target_os = "macos")]
    const CANDIDATES: &[&str] = &[
        "/System/Library/Fonts/PingFang.ttc",
        "/System/Library/Fonts/STHeiti Medium.ttc",
    ];

    #[cfg(target_os = "windows")]
    const CANDIDATES: &[&str] = &[
        "C:\\Windows\\Fonts\\msyh.ttc",
        "C:\\Windows\\Fonts\\msyh.ttf",
        "C:\\Windows\\Fonts\\simhei.ttf",
    ];

    #[cfg(target_os = "linux")]
    const CANDIDATES: &[&str] = &[
        "/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc",
        "/usr/share/fonts/truetype/noto/NotoSansCJK-Regular.ttc",
    ];

    #[allow(unused)]
    const EMPTY: &[&str] = &[];

    #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "linux")))]
    let candidates: &[&str] = EMPTY;
    #[cfg(any(target_os = "macos", target_os = "windows", target_os = "linux"))]
    let candidates: &[&str] = CANDIDATES;

    for path in candidates {
        if let Ok(bytes) = fs::read(path) {
            return Some(bytes);
        }
    }
    None
}

fn setup_cjk_fonts(ctx: &egui::Context) {
    use egui::{FontData, FontDefinitions, FontFamily};

    let Some(bytes) = load_system_cjk_font() else {
        log::warn!("No system CJK font found; egui will show tofu for CJK");
        return;
    };

    let mut fonts = FontDefinitions::default();
    fonts
        .font_data
        .insert("cjk".to_owned(), FontData::from_owned(bytes).into());

    fonts
        .families
        .entry(FontFamily::Proportional)
        .or_default()
        .insert(0, "cjk".to_owned());
    fonts
        .families
        .entry(FontFamily::Monospace)
        .or_default()
        .insert(0, "cjk".to_owned());

    ctx.set_fonts(fonts);
}

impl Scene for CjkDemo {
    fn init(&mut self, g: &mut Engine) {
        g.egui(|ctx, _g| {
            setup_cjk_fonts(ctx);
        });
    }

    fn draw(&mut self, g: &mut Engine) {
        let state = self.state.clone();

        g.egui(move |ctx, _g| {
            let mut state = match state.lock() {
                Ok(s) => s,
                Err(poisoned) => poisoned.into_inner(),
            };

            egui::Window::new("CJK 字体示例").show(ctx, |ui| {
                ui.label("下面的文本和输入框应该可以正常显示中文：");
                ui.separator();

                ui.label("静态文本：");
                ui.label("你好，世界！这是一个支持 CJK 字符的 egui 示例。");

                ui.separator();

                ui.label("可编辑文本：");
                ui.text_edit_multiline(&mut state.input);
            });
        });
    }
}

fn setup(g: &mut Engine) {
    g.set_scale_mode(ScaleMode::Fixed {
        width: 800,
        height: 600,
    });
    g.set_scene(CjkDemo::default());
}

fn main() {
    env_logger::init();
    let app = App::default()
        .title("egui CJK Demo".to_string())
        .window(UVec2::new(800, 600))
        .vsync(true)
        .resizable(true);
    app.run(setup).expect("Start game");
}
