use crate::util::copy_dir_all;
use crate::GameInstall;

// These folders are part of Titanfall 2 and
// should NEVER be used as a Profile
const SKIP_PATHS: [&str; 8] = [
    "___flightcore-temp",
    "__overlay",
    "bin",
    "Core",
    "r2",
    "vpk",
    "platform",
    "Support",
];

// A profile may have one of these to be detected
const MAY_CONTAIN: [&str; 10] = [
    "mods/",
    "plugins/",
    "packages/",
    "logs/",
    "runtime/",
    "save_data/",
    "Northstar.dll",
    "enabledmods.json",
    "placeholder.playerdata.pdata",
    "LEGAL.txt",
];

/// Returns a list of Profile names
/// All the returned Profiles can be found relative to the game path
#[tauri::command]
pub fn fetch_profiles(game_install: GameInstall) -> Result<Vec<String>, String> {
    let mut profiles: Vec<String> = Vec::new();

    for content in MAY_CONTAIN {
        let pattern = format!("{}/*/{}", game_install.game_path, content);
        for e in glob::glob(&pattern).expect("Failed to read glob pattern") {
            let path = e.unwrap();
            let mut ancestors = path.ancestors();

            ancestors.next();

            let profile_path = std::path::Path::new(ancestors.next().unwrap());
            let profile_name = profile_path
                .file_name()
                .unwrap()
                .to_os_string()
                .into_string()
                .unwrap();

            if !profiles.contains(&profile_name) {
                profiles.push(profile_name);
            }
        }
    }

    Ok(profiles)
}

/// Validates if a given profile is actually a valid profile
#[tauri::command]
pub fn validate_profile(game_install: GameInstall, profile: String) -> bool {
    // Game files are never a valid profile
    // Prevent users with messed up installs from making it even worse
    if SKIP_PATHS.contains(&profile.as_str()) {
        return false;
    }

    log::info!("Validating Profile {}", profile);

    let profile_path = format!("{}/{}", game_install.game_path, profile);
    let profile_dir = std::path::Path::new(profile_path.as_str());

    profile_dir.is_dir()
}

#[tauri::command]
pub fn delete_profile(game_install: GameInstall, profile: String) -> Result<(), String> {
    // Check if the Profile actually exists
    if !validate_profile(game_install.clone(), profile.clone()) {
        return Err(format!("{} is not a valid Profile", profile));
    }

    log::info!("Deleting Profile {}", profile);

    let profile_path = format!("{}/{}", game_install.game_path, profile);

    match std::fs::remove_dir_all(profile_path) {
        Ok(()) => Ok(()),
        Err(err) => Err(format!("Failed to delete Profile: {}", err)),
    }
}

/// Clones a profile by simply duplicating the folder under a new name
#[tauri::command]
pub fn clone_profile(
    game_install: GameInstall,
    old_profile: String,
    new_profile: String,
) -> Result<(), String> {
    // Check if the old Profile already exists
    if !validate_profile(game_install.clone(), old_profile.clone()) {
        return Err(format!("{} is not a valid Profile", old_profile));
    }

    // Check that new Profile does not already exist
    if validate_profile(game_install.clone(), new_profile.clone()) {
        return Err(format!("{} already exists", new_profile));
    }

    log::info!("Cloning Profile {} to {}", old_profile, new_profile);

    let old_profile_path = format!("{}/{}", game_install.game_path, old_profile);
    let new_profile_path = format!("{}/{}", game_install.game_path, new_profile);

    copy_dir_all(old_profile_path, new_profile_path).unwrap();

    Ok(())
}