use tool_helper::{Error, Output};
use readmap::types::MemoryMap;
use std::{io::{BufRead, BufReader}, path::PathBuf, process::{Child, Command, Stdio}};

pub fn generate_memory_map(use_wsl: bool, input: PathBuf) -> Result<MemoryMap, Error> {
    let mut child = run_objdump(use_wsl, input)?;
    if let Some(stdout) = &mut child.stdout {
        let mut line_iter = BufReader::new(stdout).lines().map(|l| l.unwrap()).into_iter();
        
        readmap::scan(|| {
            line_iter.next()
        })
    }

    else {
        Err(Error::from_str("Failed opening \"stdout\" for objdump"))
    }    
}

pub fn get_tool_output(use_wsl: bool, input: PathBuf, mut output: Output) -> Result<Output, Error> {
    let mut child = run_objdump(use_wsl, input)?;
    if let Some(stdout) = &mut child.stdout {
        let line_iter = BufReader::new(stdout).lines().map(|l| l.unwrap()).into_iter();
        
        for line in line_iter {
            writeln!(output, "{}", line)?;
        }
        Ok(output)
    }

    else {
        Err(Error::from_str("Failed opening \"stdout\" for objdump"))
    }    
}

fn run_objdump(use_wsl: bool, input: PathBuf) -> Result<Child, Error> {
    let command_list = ["wsl", "objdump", "-x"];
    let start_idx    = {
        if use_wsl {0}
        else       {1}
    };
    let mut process = Command::new(command_list[start_idx]);

    for arg in command_list.iter().skip(start_idx + 1) {
        process.arg(arg);
    }
    process.arg(input.to_str().ok_or_else(||{Error::from_str("Failed converting input string")})?);

    Ok(process.stdout(Stdio::piped()).spawn()?)
}