const { spawn, spawnSync } = require('child_process');
const fs = require('fs')

function nodeShellExec() {

    var args = Array.from(arguments);
    var opts = args[2] = args[2] || {}
    opts.title ? null : opts.title = `${args[0]} ${args[1]  }`
    const child = spawn(...arguments);
    // // const spawn = require('child_process').spawn;
    // const s = spawn(
    //     'C:\\Program Files\\Git\\bin\\sh.exe'
    // , ['notepad', 'index'], { cwd: __dirname });

  
    var p = new Promise(function(resolve, reject){
      if(!opts.detached) {
        var messages = []; // PB : TODO -- Explore stream for Task level  aggregation to prevent interleaved messages from multiple tasks...
        var success = true;
        
        if(opts.stdio !== 'ignore') {
          child.stdout.setEncoding('utf8');
          child.stderr.setEncoding('utf8');
          child.stdout.on('data', (chunk) => { 
            chunk.trim() === '' ? null : messages.push(chunk); /* console.log('d: ' + chunk) */ 
            process.stdout.write( chunk )
          });
          child.on('error', (chunk) => { success = false; messages.push(chunk); /* console.error('e: ' + chunk) */ }  );
          child.stderr.on('data', (chunk) => { 
            if(messages.join('').indexOf('fatal: not a git repository') > -1) opts.haserrors = true; 
            messages.push(chunk); 
            process.stdout.write( chunk )
            // console.error('stderr e: ' + chunk)
          });
        }
        child.on('close', (code) => {
          var logEntry = { code, success }
          if(+code !== 0 || opts.haserrors) { success = false; logEntry = { result: `${opts.title} exited with code ${code}`, success, code }};
          if(opts.stdio !== 'ignore') {
            logEntry = { result: `${opts.title} exited with code ${code}`, messages,  code }
            logEntry.success = success;
  
            if(opts.runas){
              // success ? logEntry.success = true : null;
              fs.writeFileSync('run.log', ', ' + JSON.stringify(logEntry), {'flag':'a+'} )
            }
            else {
              // console.log( messages.join('') )
              process.stdout.write( messages.join('') )
            }
          }
          if(code !== 0 || opts.haserrors) return reject(logEntry)
          resolve(logEntry)
        });
      }
      else {
        child.unref()
        resolve(true);
      }
    });
    p.process = child; 
    return p;
}

var prompt = function(choices, label, defaultchoice){
  return this.prompter.ask(
      `${label} \n ` + Object.keys(choices).map(choice => { return `  ${(+choice) + 1}) ${choices[choice]} `}).join('\n') + `\n  default ( <= ${ defaultchoice || choices[0]} ) : `
    ).then(choice => {
      if(!choice) return defaultchoice || choices[0];
      if(choice && isNaN(+choice)) return choice;
      return choices[choice + 1];
    })
} 

const readline = require("readline");
var cli = {
    nodeShellExec
  , get prompter() {
    var prompt_interface = { 
      ask : function(q){
        // Needs to be serialized. Parallel asks are not possible.
        const clii = readline.createInterface({ input: process.stdin, output: process.stdout });
        return new Promise((resolve, reject)=>{
          clii.question(q, (answer)=>{ 
            clii.close();
            resolve(answer) 
          })
        })
      }
    }
    return prompt_interface
  }
  , prompt
}

module.exports = cli