#![windows_subsystem = "windows"]

use eframe::egui;
use std::process::{Command, Stdio};
use std::sync::mpsc::{channel, Receiver, Sender};
use std::thread;
use std::time::Duration;
use std::net::TcpStream;
use std::path::Path;
use std::fs;

// Windows API 用于设置控制台编码
#[cfg(windows)]
extern "system" {
    fn SetConsoleOutputCP(wCodePageID: u32) -> i32;
    fn SetConsoleCP(wCodePageID: u32) -> i32;
}

#[cfg(windows)]
const CP_UTF8: u32 = 65001;

fn set_utf8_encoding() {
    #[cfg(windows)]
    unsafe {
        SetConsoleOutputCP(CP_UTF8);
        SetConsoleCP(CP_UTF8);
    }
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
struct Config {
    server_ip: String,
    ffmpeg_path: String,
    stream_path: String,
}

impl Default for Config {
    fn default() -> Self {
        Self {
            server_ip: "192.168.1.100".to_string(),
            ffmpeg_path: r"D:\ScreenCast\ffmpeg\bin\ffmpeg.exe".to_string(),
            stream_path: "screen".to_string(),
        }
    }
}

impl Config {
    fn load() -> Self {
        if let Ok(content) = fs::read_to_string("config.json") {
            if let Ok(config) = serde_json::from_str(&content) {
                return config;
            }
        }
        Self::default()
    }

    fn save(&self) {
        if let Ok(json) = serde_json::to_string_pretty(self) {
            let _ = fs::write("config.json", json);
        }
    }
}

#[derive(Debug, Clone)]
struct StatusInfo {
    ffmpeg_ok: bool,
    server_ok: bool,
    port_ok: bool,
}

#[derive(Debug, Clone)]
enum Message {
    StatusUpdate(StatusInfo),
    Log(String),
    ConfigChanged(Config),
}

struct PushScreenApp {
    config: Config,
    status: StatusInfo,
    log_message: String,
    is_streaming: bool,
    rx: Receiver<Message>,
    tx: Sender<Message>,
    show_settings: bool,
    temp_config: Config,
}

impl PushScreenApp {
    fn new(cc: &eframe::CreationContext<'_>) -> Self {
        // 配置中文字体
        configure_fonts(&cc.egui_ctx);

        let config = Config::load();
        let (tx, rx) = channel();
        
        // 启动状态检查线程
        let tx_clone = tx.clone();
        let config_clone = config.clone();
        thread::spawn(move || {
            loop {
                let status = StatusInfo {
                    ffmpeg_ok: Path::new(&config_clone.ffmpeg_path).exists(),
                    server_ok: check_server(&config_clone.server_ip, 8554),
                    port_ok: check_port(&config_clone.server_ip, 8554),
                };
                let _ = tx_clone.send(Message::StatusUpdate(status));
                thread::sleep(Duration::from_secs(3));
            }
        });

        Self {
            temp_config: config.clone(),
            config,
            status: StatusInfo {
                ffmpeg_ok: false,
                server_ok: false,
                port_ok: false,
            },
            log_message: "日志: 等待启动...".to_string(),
            is_streaming: false,
            rx,
            tx,
            show_settings: false,
        }
    }

    fn start_stream(&mut self) {
        if self.is_streaming {
            return;
        }

        if !self.status.ffmpeg_ok {
            self.log_message = "日志: 错误 - FFmpeg未安装，请检查配置！".to_string();
            return;
        }

        let output_url = format!(
            "rtsp://{}:8554/{}",
            self.config.server_ip, self.config.stream_path
        );

        let args = vec![
            "-f", "gdigrab",
            "-framerate", "30",
            "-i", "desktop",
            "-c:v", "libx264",
            "-preset", "ultrafast",
            "-tune", "zerolatency",
            "-f", "rtsp",
            &output_url,
        ];

        match Command::new(&self.config.ffmpeg_path)
            .args(&args)
            .stdout(Stdio::null())
            .stderr(Stdio::null())
            .spawn()
        {
            Ok(_child) => {
                self.is_streaming = true;
                self.log_message = "日志: FFmpeg推流已启动，正在向服务器推送...".to_string();
            }
            Err(e) => {
                self.log_message = format!("日志: 错误 - 启动FFmpeg失败: {}", e);
            }
        }
    }

    fn update_config(&mut self) {
        self.config = self.temp_config.clone();
        self.config.save();
        self.log_message = "日志: 配置已更新".to_string();
        
        // 重启状态检查线程
        let tx_clone = self.tx.clone();
        let config_clone = self.config.clone();
        thread::spawn(move || {
            loop {
                let status = StatusInfo {
                    ffmpeg_ok: Path::new(&config_clone.ffmpeg_path).exists(),
                    server_ok: check_server(&config_clone.server_ip, 8554),
                    port_ok: check_port(&config_clone.server_ip, 8554),
                };
                let _ = tx_clone.send(Message::StatusUpdate(status));
                thread::sleep(Duration::from_secs(3));
            }
        });
    }
}

fn check_server(ip: &str, port: u16) -> bool {
    TcpStream::connect_timeout(
        &format!("{}:{}", ip, port).parse().unwrap(),
        Duration::from_secs(2)
    ).is_ok()
}

fn check_port(ip: &str, port: u16) -> bool {
    check_server(ip, port)
}

/// 配置中文字体支持
fn configure_fonts(ctx: &egui::Context) {
    let mut fonts = egui::FontDefinitions::default();

    let font_paths = [
        r"C:\Windows\Fonts\msyh.ttc",
        r"C:\Windows\Fonts\msyhbd.ttc",
        r"C:\Windows\Fonts\simsun.ttc",
        r"C:\Windows\Fonts\simhei.ttf",
    ];

    for font_path in &font_paths {
        if let Ok(font_data) = std::fs::read(font_path) {
            let font_name = std::path::Path::new(font_path)
                .file_stem()
                .and_then(|s| s.to_str())
                .unwrap_or("custom_font");
            
            fonts.font_data.insert(
                font_name.to_owned(),
                egui::FontData::from_owned(font_data),
            );

            fonts.families.get_mut(&egui::FontFamily::Proportional).unwrap()
                .insert(0, font_name.to_owned());
            fonts.families.get_mut(&egui::FontFamily::Monospace).unwrap()
                .push(font_name.to_owned());

            break;
        }
    }

    ctx.set_fonts(fonts);
}

impl eframe::App for PushScreenApp {
    fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
        // 接收消息
        while let Ok(msg) = self.rx.try_recv() {
            match msg {
                Message::StatusUpdate(s) => self.status = s,
                Message::Log(l) => self.log_message = l,
                Message::ConfigChanged(c) => self.config = c,
            }
        }

        // 设置窗口样式
        let mut style = (*ctx.style()).clone();
        style.spacing.window_margin = egui::Margin::same(10.0);
        ctx.set_style(style);

        egui::CentralPanel::default().show(ctx, |ui| {
            // 标题栏 + 设置按钮
            ui.horizontal(|ui| {
                ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
                    if ui.button("⚙ 设置").clicked() {
                        self.temp_config = self.config.clone();
                        self.show_settings = true;
                    }
                });
            });

            // 主标题
            ui.heading("会议投屏系统 - 主播端");
            ui.add_space(15.0);

            // 本地配置组
            egui::Frame::group(ui.style()).show(ui, |ui| {
                ui.label("本地配置");
                ui.add_space(5.0);

                // FFmpeg 状态
                ui.horizontal(|ui| {
                    let (color, text) = if self.status.ffmpeg_ok {
                        (egui::Color32::GREEN, "FFmpeg: ✓ 已安装")
                    } else {
                        (egui::Color32::RED, "FFmpeg: ✗ 未找到")
                    };
                    ui.colored_label(color, "●");
                    ui.label(text);
                });

                // 服务器连接状态
                ui.horizontal(|ui| {
                    let (color, text) = if self.status.server_ok {
                        (egui::Color32::GREEN, "服务器连接: ✓ 可连接")
                    } else {
                        (egui::Color32::from_rgb(255, 165, 0), "服务器连接: ✗ 连接失败")
                    };
                    ui.colored_label(color, "●");
                    ui.label(text);
                });

                // RTSP端口状态
                ui.horizontal(|ui| {
                    let (color, text) = if self.status.port_ok {
                        (egui::Color32::GREEN, "RTSP端口: ✓ 端口开放")
                    } else {
                        (egui::Color32::from_rgb(255, 165, 0), "RTSP端口: ✗ 端口关闭")
                    };
                    ui.colored_label(color, "●");
                    ui.label(text);
                });
            });

            ui.add_space(10.0);

            // 流信息组
            egui::Frame::group(ui.style()).show(ui, |ui| {
                ui.label("流信息");
                ui.add_space(5.0);

                ui.horizontal(|ui| {
                    ui.label("服务器IP:");
                    ui.label(&self.config.server_ip);
                });

                ui.horizontal(|ui| {
                    ui.label("推流地址:");
                    ui.label(format!("rtsp://{}:8554/{}", self.config.server_ip, self.config.stream_path));
                });

                ui.horizontal(|ui| {
                    ui.label("访问地址:");
                    ui.label(format!("http://{}:8889/webrtc.html?src={}", self.config.server_ip, self.config.stream_path));
                });
            });

            ui.add_space(15.0);

            // 开始全屏投屏按钮
            let button_text = if self.is_streaming { "🎬 停止投屏" } else { "🎬 开始全屏投屏" };
            let button_color = if self.is_streaming { 
                egui::Color32::from_rgb(183, 28, 28) 
            } else { 
                egui::Color32::from_rgb(46, 125, 50) 
            };

            let button_response = ui.add_sized(
                [ui.available_width(), 50.0],
                egui::Button::new(button_text)
                    .fill(button_color)
                    .rounding(8.0)
            );

            if button_response.clicked() {
                if self.is_streaming {
                    // 停止推流
                    #[cfg(windows)]
                    {
                        let _ = Command::new("taskkill")
                            .args(&["/F", "/IM", "ffmpeg.exe"])
                            .output();
                    }
                    self.is_streaming = false;
                    self.log_message = "日志: 推流已停止".to_string();
                } else {
                    self.start_stream();
                }
            }

            ui.add_space(10.0);

            // 日志显示区域
            egui::Frame::group(ui.style()).show(ui, |ui| {
                ui.label(&self.log_message);
            });
        });

        // 设置对话框
        if self.show_settings {
            egui::Window::new("设置")
                .collapsible(false)
                .resizable(false)
                .fixed_size([450.0, 200.0])
                .show(ctx, |ui| {
                    ui.horizontal(|ui| {
                        ui.label("服务器IP:");
                        ui.text_edit_singleline(&mut self.temp_config.server_ip);
                    });

                    ui.horizontal(|ui| {
                        ui.label("FFmpeg路径:");
                        ui.text_edit_singleline(&mut self.temp_config.ffmpeg_path);
                    });

                    ui.horizontal(|ui| {
                        ui.label("推流路径:");
                        ui.text_edit_singleline(&mut self.temp_config.stream_path);
                    });

                    ui.add_space(10.0);

                    ui.horizontal(|ui| {
                        if ui.button("确定").clicked() {
                            self.update_config();
                            self.show_settings = false;
                        }
                        if ui.button("取消").clicked() {
                            self.show_settings = false;
                        }
                    });
                });
        }
    }
}

fn main() {
    set_utf8_encoding();

    let options = eframe::NativeOptions {
        viewport: egui::ViewportBuilder::default()
            .with_inner_size([520.0, 420.0])
            .with_resizable(false),
        ..Default::default()
    };

    if let Err(e) = eframe::run_native(
        "投屏源控制",
        options,
        Box::new(|cc| Box::new(PushScreenApp::new(cc))),
    ) {
        eprintln!("应用程序错误: {}", e);
        std::process::exit(1);
    }
}
