Control your mouse cursor with your phone (windows only)
use axum::{
    extract::{ws::WebSocket, WebSocketUpgrade},
    response::IntoResponse,
    routing::get,
    Router,
};
use serde::{Deserialize, Serialize};
use tower_http::services::ServeDir;
use winput::{press, release, send, send_inputs, send_str, Action, Button, Input, Mouse, Vk};

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
enum ClickKind {
    Left,
    LeftHold,
    LeftRelease,
    Middle,
    Right,
}

#[derive(Debug, Serialize, Deserialize)]
struct Vector2 {
    x: f32,
    y: f32,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
enum ActionKind {
    Cut,
    Copy,
    Paste,
    Enter,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(untagged)]
enum Command {
    Difference { difference: Vector2 },
    Click { click: ClickKind },
    Scroll { scroll: Vector2 },
    Text { text: String },
    Action { action: ActionKind },
}

impl Command {
    fn execute(&self) {
        match self {
            Command::Difference { difference } => {
                mouse_mouve(difference);
            }
            Command::Click { click } => {
                mouse_click(click);
            }
            Command::Scroll { scroll } => {
                mouse_scroll(scroll);
            }
            Command::Text { text } => {
                keyboard_text(text);
            }
            Command::Action { action } => {
                keyboard_action(action);
            }
        };
    }
}

fn mouse_mouve(difference: &Vector2) {
    let mouse_position = Mouse::position();
    if mouse_position.is_err() {
        println!("Err (mouse_position): {}", mouse_position.unwrap_err());
        return;
    }
    let (x, y) = mouse_position.unwrap();
    let position_setting = Mouse::set_position(x + difference.x as i32, y + difference.y as i32);
    if position_setting.is_err() {
        println!("Err (position_setting): {}", position_setting.unwrap_err());
    }
}

fn mouse_click(kind: &ClickKind) {
    match kind {
        ClickKind::Left => send(Button::Left),
        ClickKind::LeftHold => press(Button::Left),
        ClickKind::LeftRelease => release(Button::Left),
        ClickKind::Middle => send(Button::Middle),
        ClickKind::Right => send(Button::Right),
    };
}

fn mouse_scroll(amount: &Vector2) {
    if amount.x != 0. {
        Mouse::scrollh(amount.x);
    }
    if amount.y != 0. {
        Mouse::scroll(amount.y);
    }
}

fn keyboard_text(text: &str) {
    send_str(text);
}

fn keyboard_action(action: &ActionKind) {
    match action {
        ActionKind::Cut => {
            send_key_with_control_modifier(Vk::X);
        }
        ActionKind::Copy => {
            send_key_with_control_modifier(Vk::C);
        }
        ActionKind::Paste => {
            send_key_with_control_modifier(Vk::V);
        }
        ActionKind::Enter => {
            send(Vk::Enter);
        }
    };
}

fn send_key_with_control_modifier(key: Vk) {
    let inputs = [
        Input::from_vk(Vk::Control, Action::Press),
        Input::from_vk(key, Action::Press),
        Input::from_vk(key, Action::Release),
        Input::from_vk(Vk::Control, Action::Release),
    ];

    send_inputs(inputs);
}

#[tokio::main]
async fn main() {
    let app = Router::new()
        .nest_service("/", ServeDir::new("public"))
        .route("/realtime", get(realtime_handler));

    let listener = tokio::net::TcpListener::bind("0.0.0.0:3004").await.unwrap();

    axum::serve(listener, app).await.unwrap();
}

#[axum::debug_handler]
async fn realtime_handler(ws: WebSocketUpgrade) -> impl IntoResponse {
    ws.on_upgrade(|ws: WebSocket| async { ws_client(ws).await })
}

async fn ws_client(mut ws: WebSocket) {
    while let Some(msg) = ws.recv().await {
        if msg.is_err() {
            println!("Err (msg): {}", msg.unwrap_err());
            continue;
        }
        let msg = msg.unwrap();

        let msg = msg.into_text();
        if msg.is_err() {
            println!("Err (and_then into_text): {}", msg.unwrap_err());
            continue;
        }
        let msg = msg.unwrap();

        if msg.is_empty() {
            println!("Err (msg.is_empty): message is empty");
            continue;
        }

        let parsed_command = serde_json::from_str::<Command>(&msg);
        if parsed_command.is_err() {
            println!("Err (parse json): {}", parsed_command.unwrap_err());
            println!("Err (parse json): msg={}", msg);
            continue;
        }
        let parsed_command: Command = parsed_command.unwrap();

        parsed_command.execute();
    }
}