swarm-engine-ui 0.1.6

CLI and Desktop UI for SwarmEngine
//! Init, Config, Open commands

use std::path::PathBuf;

use swarm_engine_core::config::{GlobalConfig, PathResolver};

#[derive(Clone, Debug, clap::ValueEnum)]
pub enum OpenTarget {
    Scenarios,
    Reports,
    Config,
    Data,
}

/// Initialize directories and config
pub fn cmd_init(project: bool) {
    if project {
        // プロジェクトローカル初期化
        let project_dir = std::env::current_dir()
            .map(|d| d.join("swarm-engine"))
            .expect("Failed to get current directory");

        println!("Initializing project-local SwarmEngine...");

        let dirs = [
            project_dir.clone(),
            project_dir.join("scenarios").join("eval"),
            project_dir.join("reports"),
        ];

        for dir in &dirs {
            if !dir.exists() {
                std::fs::create_dir_all(dir).expect("Failed to create directory");
                println!("  Created: {}", dir.display());
            }
        }

        // プロジェクト設定ファイル
        let config_path = project_dir.join("config.toml");
        if !config_path.exists() {
            let config = GlobalConfig::default();
            config
                .save_to_file(&config_path)
                .expect("Failed to save config");
            println!("  Created: {}", config_path.display());
        }

        println!("\nProject initialized at: {}", project_dir.display());
    } else {
        // グローバル初期化
        println!("Initializing SwarmEngine...");

        PathResolver::ensure_dirs().expect("Failed to create directories");

        println!(
            "  System config: {}",
            PathResolver::system_config_dir().display()
        );
        println!(
            "  User data:     {}",
            PathResolver::user_data_dir().display()
        );

        // グローバル設定ファイル
        let config_path = PathResolver::global_config_file();
        if !config_path.exists() {
            let config = GlobalConfig::default();
            config.save_global().expect("Failed to save config");
            println!("  Created: {}", config_path.display());
        }

        println!("\nInitialization complete.");
    }
}

/// Show current configuration
pub fn cmd_config() {
    let config = GlobalConfig::load_merged();

    println!("=== SwarmEngine Configuration ===\n");

    println!("Paths:");
    println!(
        "  Global config:  {}",
        PathResolver::global_config_file().display()
    );
    if let Some(project) = PathResolver::project_config_file() {
        println!(
            "  Project config: {} {}",
            project.display(),
            if project.exists() {
                "(found)"
            } else {
                "(not found)"
            }
        );
    }
    println!(
        "  User data:      {}",
        config.resolved_user_data_dir().display()
    );
    println!(
        "  Reports:        {}",
        config.resolved_reports_dir().display()
    );

    println!("\nEval:");
    println!("  Default runs:     {}", config.eval.default_runs);
    println!("  Default parallel: {}", config.eval.default_parallel);
    println!(
        "  Tick duration:    {}ms",
        config.eval.target_tick_duration_ms
    );

    println!("\nLogging:");
    println!("  Level: {:?}", config.logging.level);
    println!("  File:  {}", config.logging.file_enabled);

    println!("\nDesktop:");
    println!("  Theme: {:?}", config.desktop.theme);
}

/// Open directory in file manager
#[allow(clippy::zombie_processes)] // Fire-and-forget: we don't wait for file manager to close
pub fn cmd_open(target: OpenTarget) {
    let path: PathBuf = match target {
        OpenTarget::Scenarios => PathResolver::user_eval_scenarios_dir(),
        OpenTarget::Reports => PathResolver::reports_dir(),
        OpenTarget::Config => PathResolver::system_config_dir(),
        OpenTarget::Data => PathResolver::user_data_dir(),
    };

    if !path.exists() {
        eprintln!("Directory does not exist: {}", path.display());
        eprintln!("Run 'swarm-engine init' first.");
        std::process::exit(1);
    }

    println!("Opening: {}", path.display());

    #[cfg(target_os = "macos")]
    {
        std::process::Command::new("open")
            .arg(&path)
            .spawn()
            .expect("Failed to open directory");
    }

    #[cfg(target_os = "linux")]
    {
        std::process::Command::new("xdg-open")
            .arg(&path)
            .spawn()
            .expect("Failed to open directory");
    }

    #[cfg(target_os = "windows")]
    {
        std::process::Command::new("explorer")
            .arg(&path)
            .spawn()
            .expect("Failed to open directory");
    }
}