// SPDX-FileCopyrightText: 2023 CELESTIFYX Team
// SPDX-License-Identifier: GPL-3.0-or-later

use std::{
    fs,
    io::Error,

    path::{
        Path,
        PathBuf
    }
};

#[derive(Debug, Clone, PartialEq, Eq)]
pub(super) struct Repo {
    pub(super) name: String,
    pub(super) path: PathBuf
}

impl Repo {
    pub(super) fn exists_on_disk(&self) -> bool {
        self.path.is_dir()
    }
}

#[derive(Debug, Clone)]
pub(super) struct RepoPaths {
    pub(super) repo_list:    PathBuf,
    pub(super) installed_db: PathBuf
}

#[derive(Debug, thiserror::Error)]
pub(super) enum RepoError {
    #[error("failed to read repo list at {:?}: {}", path, source)]
    Read {
        path: PathBuf,
        #[source]
        source: Error
    }
}

fn parse_repo_line(line: &str) -> Option<&str> {
    let trimmed: &str = line.trim();

    if trimmed.is_empty() || trimmed.starts_with('#') {
        return None;
    }

    trimmed.split_whitespace().next()
}

pub(super) fn load_repos(paths: &RepoPaths) -> Result<Vec<Repo>, RepoError> {
    let contents: String = fs::read_to_string(&paths.repo_list).map_err(|source: Error| RepoError::Read {
        path: paths.repo_list.clone(),
        source
    })?;

    let repos: Vec<Repo> = contents.lines().filter_map(parse_repo_line).map(|name: &str| {
        let path: PathBuf = repo_dir_for(&paths.repo_list, name);

        Repo {
            name: name.to_string(),
            path
        }
    }).collect();

    Ok(repos)
}

fn repo_dir_for(repo_list: &Path, name: &str) -> PathBuf {
    repo_list.parent().unwrap_or_else(|| Path::new("/")).join(name)
}
