//! main.rs — Dual-CSS HF Mode
//! Entry point: applies the dark theme, runs startup environment checks, loads
//! config, and launches the egui/eframe window.

mod app;
mod audio;
mod config;
mod dsp;
mod flrig;
mod gpu_fft;
mod ptt;
mod settings;
mod waterfall;

use app::DualCssApp;
use config::ConfigManager;

/// Build the dark visual theme, translated from the Qt DARK_STYLE stylesheet.
/// Palette: bg #0d1117, panel #0e141b, accent #00d4ff, text #c9d1d9.
fn apply_dark_theme(ctx: &egui::Context) {
    use egui::{Color32, CornerRadius, Stroke};

    let mut visuals = egui::Visuals::dark();
    let bg = Color32::from_rgb(13, 17, 23); // #0d1117
    let panel = Color32::from_rgb(14, 20, 27); // #0e141b
    let field = Color32::from_rgb(8, 12, 16); // #080c10
    let border = Color32::from_rgb(26, 37, 53); // #1a2535
    let accent = Color32::from_rgb(0, 212, 255); // #00d4ff
    let text = Color32::from_rgb(201, 209, 217); // #c9d1d9

    visuals.override_text_color = Some(text);
    visuals.panel_fill = bg;
    visuals.window_fill = panel;
    visuals.extreme_bg_color = field;
    visuals.faint_bg_color = panel;
    visuals.window_stroke = Stroke::new(1.0, border);
    visuals.selection.bg_fill = border;
    visuals.selection.stroke = Stroke::new(1.0, accent);
    visuals.hyperlink_color = accent;

    let radius = CornerRadius::same(4);
    visuals.widgets.noninteractive.bg_fill = panel;
    visuals.widgets.noninteractive.bg_stroke = Stroke::new(1.0, border);
    visuals.widgets.inactive.bg_fill = panel;
    visuals.widgets.inactive.bg_stroke = Stroke::new(1.0, Color32::from_rgb(42, 63, 85));
    visuals.widgets.inactive.corner_radius = radius;
    visuals.widgets.hovered.bg_fill = border;
    visuals.widgets.hovered.bg_stroke = Stroke::new(1.0, accent);
    visuals.widgets.hovered.corner_radius = radius;
    visuals.widgets.active.bg_fill = accent;
    visuals.widgets.active.bg_stroke = Stroke::new(1.0, accent);
    visuals.widgets.active.corner_radius = radius;

    ctx.set_visuals(visuals);
}

/// Warn about conditions that break audio/PTT. Returns human-readable messages.
fn check_environment() -> Vec<String> {
    let mut warnings = Vec::new();

    // Running as root breaks per-user audio (PulseAudio/PipeWire) on Linux.
    #[cfg(unix)]
    {
        // SAFETY: geteuid() is always safe; it just reads the effective UID.
        let euid = unsafe { libc_geteuid() };
        if euid == 0 {
            warnings.push(
                "Running as root will break audio on Linux.\n\n\
                 Audio belongs to your user session (PulseAudio/PipeWire).\n\
                 Exit and run without sudo.\n\n\
                 For serial PTT access, add yourself to the dialout group:\n\
                 \tsudo usermod -a -G dialout $USER"
                    .to_string(),
            );
        }
    }

    warnings
}

#[cfg(unix)]
extern "C" {
    #[link_name = "geteuid"]
    fn libc_geteuid() -> u32;
}

fn main() -> eframe::Result<()> {
    // Silence ALSA probe spam before any audio enumeration (Linux only no-op
    // elsewhere). Must run before AudioEngine touches cpal.
    audio::suppress_alsa_errors();

    for warning in check_environment() {
        eprintln!("[Startup warning]\n{warning}\n");
    }

    let cfg = ConfigManager::new();

    let native_options = eframe::NativeOptions {
        viewport: egui::ViewportBuilder::default()
            .with_inner_size([880.0, 640.0])
            .with_min_inner_size([860.0, 620.0])
            .with_title("Dual-CSS HF Mode"),
        ..Default::default()
    };

    eframe::run_native(
        "Dual-CSS HF Mode",
        native_options,
        Box::new(|cc| {
            apply_dark_theme(&cc.egui_ctx);
            Ok(Box::new(DualCssApp::new(cfg)))
        }),
    )
}
