//use serde::{Deserialize, Serialize};
//use serde_json::{self, json};

use std::collections::HashMap;
use std::env;
use std::fs;
use std::io::{BufRead, BufReader};
use std::os::unix::net::UnixStream;
use std::process::Command;
use std::str;
use std::string::String;
use std::thread::sleep;
use std::time::Duration;

const DESKTOP_PATH: &str = "/run/current-system/sw/share/applications/";
const ENV_INSTANCE_SIGNATURE: &str = "HYPRLAND_INSTANCE_SIGNATURE";

//struct Workspace {
//    id: i32,
//    active_on: u32,
//    num_windows: u32,
//    icon: String,
//}

//fn fetch_workspaces() {}

fn fetch_monitors() {
    let monitors = Command::new("hyprctl monitors").arg("-j").output();
    let monitors = match monitors {
        Ok(monitor) => monitor.stdout,
        Err(_error) => b"Monitor error".to_vec(),
    };
}

//fn fetch_clients() {}

fn generate_icon_map() -> HashMap<String, String> {
    let files = fs::read_dir(DESKTOP_PATH).unwrap();

    let mut vector = vec![];

    let mut i = 0;

    for file in files {
        let file = match file {
            Ok(file) => file,
            Err(_) => continue,
        };
        let path = file.path();
        let extension = path.extension().expect("error");

        if extension != "desktop" {
            continue;
        }

        let mut class = String::new();
        let mut icon = String::new();

        let file = fs::read_to_string(path).unwrap();

        let mut got_icon = false;
        let mut got_class = false;

        for line in file.lines() {
            let line = line.replace(' ', "");
            match (got_icon, &line) {
                (true, _) => (),
                (false, line) if line.starts_with("Icon=") => {
                    icon = line.split_once('=').expect("error").1.to_string();
                    got_icon = true;
                    if got_class {
                        break;
                    }
                    continue;
                }
                _ => (),
            }

            match (got_class, &line) {
                (true, _) => (),
                (false, line) if line.starts_with("StartupWMClass=") => {
                    class = line.split_once('=').expect("error").1.to_string();
                    got_class = true;
                    if got_icon {
                        break;
                    }
                    continue;
                }
                (false, line) if line.starts_with("Name=") => {
                    class = line.split_once('=').expect("error").1.to_string();
                    continue;
                }
                _ => (),
            }
        }
        vector.push((class, icon));
        i += 1;
    }

    let mut icon_map: HashMap<String, String> = HashMap::with_capacity(i);
    icon_map.extend(vector);

    for (key, value) in &icon_map {
        println!("Key: {}, Value: {}", key, value);
    }

    icon_map
}

fn handle_workspace() {
    fetch_monitors();
}
fn handle_moveworkspace() {}
fn handle_activespecial() {}
fn handle_openwindow() {}
fn handle_closewindow() {}
fn handle_movewindow() {}
fn handle_activewindow() {}

fn handle(message: &str) {
    println!("{}", message);
    match message {
        s if s.starts_with("workspacev2>>") => handle_workspace(),
        s if s.starts_with("moveworkspacev2>>") => handle_moveworkspace(),
        s if s.starts_with("activespecial>>") => handle_activespecial(),
        s if s.starts_with("openwindow>>") => handle_openwindow(),
        s if s.starts_with("closewindow>>") => handle_closewindow(),
        s if s.starts_with("movewindowv2>>") => handle_movewindow(),
        s if s.starts_with("activewindow>>v2") => handle_activewindow(),
        _ => (),
    };
}

fn main() {
    let icon_map = generate_icon_map();

    let hyprland_instance_signature = env::var(ENV_INSTANCE_SIGNATURE).unwrap();
    let address = format!(
        "/run/user/1000/hypr/{}/.socket2.sock",
        hyprland_instance_signature
    );
    let stream = UnixStream::connect(address).unwrap();
    let mut reader = BufReader::new(stream);

    loop {
        let mut buf = String::new();
        reader.read_line(&mut buf).unwrap();
        handle(buf.trim());
        sleep(Duration::from_millis(100));
    }
}
