print all conflicts in the current channel
//! This file is copy-pasted directly from the pijul source code
use std::path::PathBuf;

use anyhow::bail;
use libpijul::DOT_DIR;
use log::debug;

pub fn current_dir() -> Result<PathBuf, anyhow::Error> {
    if let Ok(cur) = std::env::current_dir() {
        Ok(cur)
    } else {
        bail!("Cannot access working directory")
    }
}

pub struct Repository {
    pub pristine: libpijul::pristine::sanakirja::Pristine,
    pub changes: libpijul::changestore::filesystem::FileSystem,
    pub working_copy: libpijul::working_copy::filesystem::FileSystem,
    //pub config: config::Config,
    pub path: PathBuf,
    pub changes_dir: PathBuf,
}

pub const PRISTINE_DIR: &str = "pristine";
pub const CHANGES_DIR: &str = "changes";
//pub const CONFIG_FILE: &str = "config";

#[cfg(unix)]
pub fn max_files() -> usize {
    let n = if let Ok((n, _)) = rlimit::getrlimit(rlimit::Resource::NOFILE) {
        (n as usize / (2 * num_cpus::get())).max(1)
    } else {
        256
    };
    debug!("max_files = {:?}", n);
    n
}

#[cfg(not(unix))]
pub fn max_files() -> usize {
    1
}

impl Repository {
    fn find_root_(cur: Option<PathBuf>, dot_dir: &str) -> Result<PathBuf, anyhow::Error> {
        let mut cur = if let Some(cur) = cur {
            cur
        } else {
            current_dir()?
        };
        cur.push(dot_dir);
        loop {
            debug!("{:?}", cur);
            if std::fs::metadata(&cur).is_err() {
                cur.pop();
                if cur.pop() {
                    cur.push(DOT_DIR);
                } else {
                    bail!("No Pijul repository found")
                }
            } else {
                break;
            }
        }
        Ok(cur)
    }

    pub fn find_root(cur: Option<PathBuf>) -> Result<Self, anyhow::Error> {
        Self::find_root_with_dot_dir(cur, DOT_DIR)
    }

    pub fn find_root_with_dot_dir(
        cur: Option<PathBuf>,
        dot_dir: &str,
    ) -> Result<Self, anyhow::Error> {
        let cur = Self::find_root_(cur, dot_dir)?;
        let mut pristine_dir = cur.clone();
        pristine_dir.push(PRISTINE_DIR);
        let mut changes_dir = cur.clone();
        changes_dir.push(CHANGES_DIR);
        let mut working_copy_dir = cur.clone();
        working_copy_dir.pop();
        // let config_path = cur.join(CONFIG_FILE);
        // let config = if let Ok(config) = std::fs::read(&config_path) {
        //     if let Ok(toml) = toml::from_slice(&config) {
        //         toml
        //     } else {
        //         bail!("Could not read configuration file at {:?}", config_path)
        //     }
        // } else {
        //     config::Config::default()
        // };
        Ok(Repository {
            pristine: libpijul::pristine::sanakirja::Pristine::new(&pristine_dir.join("db"))?,
            working_copy: libpijul::working_copy::filesystem::FileSystem::from_root(
                &working_copy_dir,
            ),
            changes: libpijul::changestore::filesystem::FileSystem::from_root(
                &working_copy_dir,
                crate::repository::max_files(),
            ),
            //config,
            path: working_copy_dir,
            changes_dir,
        })
    }

    // pub fn update_config(&self) -> Result<(), anyhow::Error> {
    //     std::fs::write(
    //         self.path.join(DOT_DIR).join("config"),
    //         toml::to_string(&self.config)?,
    //     )?;
    //     Ok(())
    // }
}

// fn init_default_config(path: &std::path::Path, remote: Option<&str>) -> Result<(), anyhow::Error> {
//     use std::io::Write;
//     let mut path = path.join(DOT_DIR);
//     path.push("config");
//     if std::fs::metadata(&path).is_err() {
//         let mut f = std::fs::File::create(&path)?;
//         if let Some(rem) = remote {
//             writeln!(f, "default_remote = {:?}", rem)?;
//         }
//         writeln!(f, "[hooks]\nrecord = []")?;
//     }
//     Ok(())
// }