use night_fury_core::BrowserSession;
use serde_json::json;

use crate::output::{output_err, output_ok, OutputMode};

pub async fn dispatch(session: &BrowserSession, parts: &[&str], mode: OutputMode) {
    let sub = parts.first().copied().unwrap_or("");
    match sub {
        "tap" => tap(session, &parts[1..], mode).await,
        "swipe" => swipe(session, &parts[1..], mode).await,
        other => output_err(
            mode,
            &format!("Unknown touch subcommand: {other}. Use 'tap <x> <y>' or 'swipe <x1> <y1> <x2> <y2>'"),
        ),
    }
}

async fn tap(session: &BrowserSession, parts: &[&str], mode: OutputMode) {
    if parts.len() < 2 {
        output_err(mode, "Usage: touch tap <x> <y>");
        return;
    }
    let x: f64 = match parts[0].parse() {
        Ok(v) => v,
        Err(_) => {
            output_err(mode, "x must be a number");
            return;
        }
    };
    let y: f64 = match parts[1].parse() {
        Ok(v) => v,
        Err(_) => {
            output_err(mode, "y must be a number");
            return;
        }
    };
    match session.tap(x, y).await {
        Ok(msg) => output_ok(mode, &msg, json!({"action": "touch_tap", "x": x, "y": y})),
        Err(e) => output_err(mode, &e.to_string()),
    }
}

async fn swipe(session: &BrowserSession, parts: &[&str], mode: OutputMode) {
    if parts.len() < 4 {
        output_err(mode, "Usage: touch swipe <x1> <y1> <x2> <y2>");
        return;
    }
    let x1: f64 = match parts[0].parse() {
        Ok(v) => v,
        Err(_) => {
            output_err(mode, "x1 must be a number");
            return;
        }
    };
    let y1: f64 = match parts[1].parse() {
        Ok(v) => v,
        Err(_) => {
            output_err(mode, "y1 must be a number");
            return;
        }
    };
    let x2: f64 = match parts[2].parse() {
        Ok(v) => v,
        Err(_) => {
            output_err(mode, "x2 must be a number");
            return;
        }
    };
    let y2: f64 = match parts[3].parse() {
        Ok(v) => v,
        Err(_) => {
            output_err(mode, "y2 must be a number");
            return;
        }
    };
    match session.swipe(x1, y1, x2, y2).await {
        Ok(msg) => output_ok(
            mode,
            &msg,
            json!({"action": "touch_swipe", "x1": x1, "y1": y1, "x2": x2, "y2": y2}),
        ),
        Err(e) => output_err(mode, &e.to_string()),
    }
}
