use std::os::unix::prelude::CommandExt;
use super::{Action, ActionError};
pub struct CommandAction {
    pub path: String,
    pub args: Vec<String>,
}
pub struct ShellCommandAction {
    pub command: String,
}
impl Action for CommandAction {
    fn execute(&mut self) -> Result<(), ActionError> {
        log::debug!("Execute command {} {:?}", self.path, self.args);
        std::process::Command::new(&self.path)
            .args(self.args.iter())
            .stdin(std::process::Stdio::null())
            .stdout(std::process::Stdio::inherit())
            .stderr(std::process::Stdio::inherit())
            .detach()?;
        log::trace!("Spawned the command");
        Ok(())
    }
}
impl Action for ShellCommandAction {
    fn execute(&mut self) -> Result<(), ActionError> {
        log::debug!("Execute command {:?}", self.command);
        std::process::Command::new("/bin/sh")
            .arg("-c")
            .arg(&self.command)
            .stdout(std::process::Stdio::inherit())
            .stderr(std::process::Stdio::inherit())
            .detach()?;
        log::trace!("Spawned the command");
        Ok(())
    }
}
/// Extension to be able to detach child processes without creating zombies
trait DetachExt {
    fn detach(&mut self) -> std::io::Result<()>;
}
impl DetachExt for std::process::Command {
    fn detach(&mut self) -> std::io::Result<()> {
        // Safety: usual daemonization stuff. Parent exits immediately before
        // exec, child goes on to exec what it wants
        use nix::unistd::ForkResult;
        unsafe {
            self.pre_exec(|| {
                match nix::unistd::fork().unwrap() {
                    ForkResult::Parent { child: _ } => std::process::exit(0),
                    ForkResult::Child => (),
                }
                Ok(())
            })
        }
        .status()
        .map(|_| ())
    }
}
impl From<std::io::Error> for ActionError {
    fn from(err: std::io::Error) -> ActionError {
        ActionError(format!("{}", err))
    }
}