use std::process::{Command, Stdio};
use std::path::Path;
use color_print::cprintln;

fn trim_newline(s: &mut String) {
    if s.ends_with('\n') {
        s.pop();
        if s.ends_with('\r') {
            s.pop();
        }
    }
}

fn main() {
   {
        // Tell user that we are going to start the update procedure
        cprintln!("<bold><rev><white>osupdater : rust edition</white></rev></bold>\n");
        cprintln!("<bold><rev><white>This tool will locate any package managers on your system and run the update tool appropriate to it.</white></rev></bold>\n");
        cprintln!("<bold><rev><white>Looking for native package managers.</white></rev></bold>\n");
        let find_sudo = Command::new("which")
            .arg("sudo").stdout(Stdio::piped()).output().unwrap();
        let mut sudo_bin = String::from_utf8(find_sudo.stdout).unwrap();
        trim_newline(&mut sudo_bin);
               
        let find_apt = Command::new("which")
            .arg("apt").stdout(Stdio::piped()).output().unwrap();
        let mut apt_bin = String::from_utf8(find_apt.stdout).unwrap();
        trim_newline(&mut apt_bin);
        
        let find_dnf = Command::new("which")
            .arg("dnf").stdout(Stdio::piped()).output().unwrap();
        let mut dnf_bin = String::from_utf8(find_dnf.stdout).unwrap();
        trim_newline(&mut dnf_bin);

        let find_pacman = Command::new("which")
            .arg("pacman").stdout(Stdio::piped()).output().unwrap();
        let mut pacman_bin = String::from_utf8(find_pacman.stdout).unwrap();
        trim_newline(&mut pacman_bin);

        let find_urpmi = Command::new("which")
            .arg("urpmi").stdout(Stdio::piped()).output().unwrap();
        let mut urpmi_bin = String::from_utf8(find_urpmi.stdout).unwrap();
        trim_newline(&mut urpmi_bin);

        let find_yum = Command::new("which")
            .arg("yum").stdout(Stdio::piped()).output().unwrap();
        let mut yum_bin = String::from_utf8(find_yum.stdout).unwrap();
        trim_newline(&mut yum_bin);
        
        let find_zypper = Command::new("which")
            .arg("zypper").stdout(Stdio::piped()).output().unwrap();
        let mut zypper_bin = String::from_utf8(find_zypper.stdout).unwrap();
        trim_newline(&mut zypper_bin);
                        
        let find_flatpak = Command::new("which")
            .arg("flatpak").stdout(Stdio::piped()).output().unwrap();
        let mut flatpak_bin = String::from_utf8(find_flatpak.stdout).unwrap();
        trim_newline(&mut flatpak_bin);

        let find_snap = Command::new("which")
            .arg("snap").stdout(Stdio::piped()).output().unwrap();
        let mut snap_bin = String::from_utf8(find_snap.stdout).unwrap();
        trim_newline(&mut snap_bin);        
        
        let find_pip_review = Command::new("which")
            .arg("pip-review").stdout(Stdio::piped()).output().unwrap();
        let mut pip_review_bin = String::from_utf8(find_pip_review.stdout).unwrap();             
        trim_newline(&mut pip_review_bin);
        
        //apt
        cprintln!("<bold><rev><magenta>Checking for apt</magenta></rev></bold>");
        let path = Path::new(&apt_bin);
        if path.exists(){
            let mut cmd = 
                Command::new(&sudo_bin)
                .arg(&apt_bin).arg("update").arg("-y")
                .stdout(Stdio::inherit()).stderr(Stdio::inherit())
                .spawn().unwrap();
            let _output = cmd.wait();
            let mut cmd = 
                Command::new(&sudo_bin)
                .arg(&apt_bin).arg("upgrade").arg("-y")
                .stdout(Stdio::inherit()).stderr(Stdio::inherit())
                .spawn().unwrap();
            let _output = cmd.wait();
        }
    
        // dnf
        cprintln!("<bold><rev><blue>hecking for dnf</blue></rev></bold>");
        let path = Path::new(&dnf_bin);
        if path.exists(){
            let mut cmd = 
                Command::new(&sudo_bin)
                .arg(&dnf_bin).arg("--refresh").arg("--skip-broken").arg("--nobest").arg("-y").arg("update")
                .stdout(Stdio::inherit()).stderr(Stdio::inherit())
                .spawn().unwrap();
            let _output = cmd.wait();
        }
    
        // pacman
        cprintln!("<bold><rev><cyan>Checking for pacman</cyan></rev></bold>");
        let path = Path::new(&pacman_bin);
        if path.exists(){
            let mut cmd = 
                Command::new(&sudo_bin)
                .arg(&pacman_bin).arg("-Syu")
                .stdout(Stdio::inherit()).stderr(Stdio::inherit())
                .spawn().unwrap();
            let _output = cmd.wait();
        }
    
        // urpmi
        cprintln!("<bold><rev><white>Checking for urpmi</white></rev></bold>");
        let path = Path::new(&urpmi_bin);
        if path.exists(){
            let mut cmd = 
                Command::new(&sudo_bin)
                .arg(&urpmi_bin).arg("--auto-update").arg("-y")
                .stdout(Stdio::inherit()).stderr(Stdio::inherit())
                .spawn().unwrap();
                let _output = cmd.wait();
        }
    
        // yum
        cprintln!("<bold><rev><red>Checking for yum</red></rev></bold>");
        let path = Path::new(&yum_bin);
        if path.exists(){
            let mut cmd = 
                Command::new(&sudo_bin)
                .arg(&yum_bin).arg("--refresh").arg("--skip-broken").arg("--nobest").arg("-y").arg("update")
                .stdout(Stdio::inherit()).stderr(Stdio::inherit())
                .spawn().unwrap();
            let _output = cmd.wait();
        }
    
        // zypper
        cprintln!("<bold><rev><green>Checking for zypper</green></rev></bold>");
        let path = Path::new(&zypper_bin);
        if path.exists(){
            let mut cmd = 
                Command::new(&sudo_bin)
                .arg(&zypper_bin).arg("in").arg("-y")
                .stdout(Stdio::inherit()).stderr(Stdio::inherit())
                .spawn().unwrap();
            let _output = cmd.wait();
        }
   
       // Check container formats
       cprintln!("<bold><rev><white>Checking application containers</white></rev></bold>");
             
       
       // flatpak
       cprintln!("<bold><rev><blue>Checking for user flatpak installs</blue></rev></bold>");
       let path = Path::new(&flatpak_bin);
       if path.exists(){
           let mut cmd = 
               Command::new(&flatpak_bin)
               .arg("update").arg("--user").arg("-y")
               .stdout(Stdio::inherit()).stderr(Stdio::inherit())
               .spawn().unwrap();
           let _output = cmd.wait(); 
       }
       cprintln!("<bold><rev><blue>Checking for system flatpak installs</blue></rev></bold>");
       let path = Path::new(&flatpak_bin);
       if path.exists(){
           let mut cmd = 
               Command::new(&sudo_bin)
               .arg(&flatpak_bin).arg("update").arg("-y")
               .stdout(Stdio::inherit()).stderr(Stdio::inherit())
               .spawn().unwrap();
           let _output = cmd.wait(); 
       }

       // snap
       cprintln!("<bold><rev><magenta>Checking for user snap installation</magenta></rev></bold>");
       let path = Path::new(&snap_bin);
       if path.exists(){
           let mut cmd = 
               Command::new(&snap_bin)
               .arg("refresh").arg("-y")
               .stdout(Stdio::inherit()).stderr(Stdio::inherit())
               .spawn().unwrap();
           let _output = cmd.wait();   
       }
       cprintln!("<bold><rev><magenta>Checking for system snap installation</magenta></rev></bold>");
       let path = Path::new(&snap_bin);
       if path.exists(){
           let mut cmd = 
               Command::new(&sudo_bin)
               .arg(&snap_bin).arg("refresh").arg("-y")
               .stdout(Stdio::inherit()).stderr(Stdio::inherit())
               .spawn().unwrap();
           let _output = cmd.wait();   
       }     
   
       //Python
       cprintln!("<bold><rev><red>Updating Python user installation via pip-review</red></rev></bold>");
       let path = Path::new(&pip_review_bin);
       if path.exists(){
           let mut cmd = 
               Command::new(&pip_review_bin)
               .arg("--auto").arg("--local").arg("--user")
               .stdout(Stdio::inherit()).stderr(Stdio::inherit())
               .spawn().unwrap();
           let _output = cmd.wait();
       }
   }  
}
