// client/src/layout.rs  - Wayland-only window placement utilities
#![forbid(unsafe_code)]

use serde_json::Value;
use std::process::Command;
use tracing::{info, warn};

/// The three layouts we cycle through.
#[derive(Clone, Copy)]
pub enum Layout {
    SideBySide, // two halves on the current monitor
    FullLeft,   // left eye full-screen, right hidden
    FullRight,  // right eye full-screen, left hidden
}

/// Move/resize a window titled “Lesavka-eye-{eye}” using `swaymsg`.
fn place_window(eye: u32, x: i32, y: i32, w: i32, h: i32) {
    let title = format!("Lesavka-eye-{eye}");
    let cmd = format!(r#"[title="^{title}$"] resize set {w} {h}; move position {x} {y}"#);

    match Command::new("swaymsg").arg(cmd).status() {
        Ok(st) if st.success() => info!("✅ placed eye{eye} {w}×{h}@{x},{y}"),
        Ok(st) => warn!("⚠️ swaymsg exited with {st}"),
        Err(e) => warn!("⚠️ swaymsg failed: {e}"),
    }
}

/// Apply a layout on the currently focused output.
///
/// Inputs: the requested two-eye layout mode.
/// Outputs: none; the function shells out to `swaymsg` to move and resize the
/// active video windows in place.
/// Why: the UI keeps layout policy in one helper so the command construction
/// stays testable even though the actual window management is side-effectful.
pub fn apply(layout: Layout) {
    let out = match Command::new("swaymsg")
        .args(["-t", "get_outputs", "-r"])
        .output()
    {
        Ok(o) => o.stdout,
        Err(e) => {
            warn!("get_outputs failed: {e}");
            return;
        }
    };

    let Ok(Value::Array(outputs)) = serde_json::from_slice::<Value>(&out) else {
        warn!("unexpected JSON from swaymsg");
        return;
    };
    let Some(rect) = outputs
        .iter()
        .find(|o| o.get("focused").and_then(Value::as_bool) == Some(true))
        .and_then(|o| o.get("rect"))
    else {
        return;
    };

    // helper to read an i64 → i32 with defaults
    let g = |k: &str| rect.get(k).and_then(Value::as_i64).unwrap_or(0) as i32;
    let (x, y, w, h) = (g("x"), g("y"), g("width"), g("height"));

    match layout {
        Layout::SideBySide => {
            let w_half = w / 2;
            place_window(0, x, y, w_half, h);
            place_window(1, x + w_half, y, w_half, h);
        }
        Layout::FullLeft => {
            place_window(0, x, y, w, h);
            place_window(1, x + w * 2, y + h * 2, 1, 1); // off-screen
        }
        Layout::FullRight => {
            place_window(1, x, y, w, h);
            place_window(0, x + w * 2, y + h * 2, 1, 1);
        }
    }
}
