Documentation
use std::process::Command;

use std::{fs, path, process};

use anyhow::anyhow;

pub fn samtools_bai(bam_file: &str, force: bool, threads: Option<usize>) -> anyhow::Result<()> {
    let res_filepath = format!("{}.bai", bam_file);

    let threads = threads.unwrap_or(num_cpus::get_physical() / 2);
    let threads = if threads > 1 { threads } else { 1 };

    if force {
        if path::Path::new(&res_filepath).exists() {
            fs::remove_file(&res_filepath).expect(&format!("remove {} error", res_filepath));
        }
    }

    let mut index_cmd = process::Command::new("samtools");

    index_cmd.args([
        "index",
        "-@",
        threads.to_string().as_str(),
        bam_file,
        &res_filepath,
    ]);

    if let Ok(res) = index_cmd.status() {
        if !res.success() {
            return Err(anyhow!(
                "Run cmd error, exit status not succ: {:?}",
                index_cmd
            ));
        }
    } else {
        return Err(anyhow!("Run cmd error: {:?}", index_cmd));
    }

    Ok(())
}

pub fn sort_by_coordinates(bam_file: &str, threads: Option<usize>) {
    let threads = threads.unwrap_or(num_cpus::get_physical() / 2);
    let threads = if threads > 1 { threads } else { 1 };

    let mut cmd = Command::new("samtools");
    cmd.args([
        "sort",
        "-o",
        bam_file,
        "-@",
        threads.to_string().as_str(),
        bam_file,
    ]);

    let oup = cmd.output().expect(&format!("sort {} error", bam_file));
    if !oup.status.success() {
        panic!(
            "sort {} error. {}",
            bam_file,
            String::from_utf8(oup.stderr).unwrap()
        );
    }
}

pub fn sort_by_tag(bam_file: &str, tag: &str, threads: Option<usize>) -> String {
    let threads = threads.unwrap_or(num_cpus::get_physical() / 2);
    let out_bam = format!(
        "{}.sort_by_{}.bam",
        bam_file.rsplit_once(".").unwrap().0,
        tag
    );

    let mut cmd = Command::new("samtools");
    cmd.args([
        "sort",
        "-n",
        "-t",
        tag,
        "-o",
        out_bam.as_str(),
        "-@",
        threads.to_string().as_str(),
        bam_file,
    ]);

    let oup = cmd.output().expect(&format!("sort {} error", bam_file));
    if !oup.status.success() {
        panic!(
            "sort {} error. {}",
            bam_file,
            String::from_utf8(oup.stderr).unwrap()
        );
    }

    out_bam
}