kube-copy 0.1.0

A lightweight CLI utility to automatically synchronize local files into Kubernetes pods
use crate::controller::Controller;
use notify::{EventKind, RecommendedWatcher, RecursiveMode, Watcher};
use std::collections::HashMap;
use std::path::Path;
use std::sync::{Arc, Mutex};
use tokio::sync::mpsc;
use tokio::task::JoinHandle;
use tokio::time::{sleep, Duration};

pub struct FsWatcher;

impl FsWatcher {
    pub async fn watch(src_path: String, controller: Arc<Controller>) {
        let (tx, mut rx) = mpsc::channel(1);
        let debounce_tasks: Arc<Mutex<HashMap<String, JoinHandle<()>>>> =
            Arc::new(Mutex::new(HashMap::new()));

        let mut watcher = RecommendedWatcher::new(
            move |res| {
                let _ = tx.blocking_send(res);
            },
            notify::Config::default(),
        )
        .expect("Failed to initialize watcher");

        watcher
            .watch(Path::new(&src_path), RecursiveMode::Recursive)
            .expect("Failed to watch directory");

        println!("👀 Watching directory: {}", src_path);

        while let Some(Ok(event)) = rx.recv().await {
            if matches!(
                event.kind,
                EventKind::Modify(_) | EventKind::Create(_) | EventKind::Remove(_)
            ) {
                println!("📦 File system change detected at: {:?}", event.paths);
                let key = src_path.clone();
                let ctrl = controller.clone();
                let debounce_tasks = debounce_tasks.clone();

                let key_for_task = key.clone();

                if let Some(handle) = debounce_tasks.lock().unwrap().remove(&key) {
                    handle.abort();
                }

                let handle = tokio::spawn(async move {
                    sleep(Duration::from_millis(1000)).await;
                    println!("✅ Debounced sync for {}", key_for_task);
                    ctrl.on_fs_change(key_for_task).await;
                });

                debounce_tasks.lock().unwrap().insert(key, handle);
            }
        }
    }
}