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 spawn = require('child_process').spawn;
    // const s = spawn(
    //     'C:\\Program Files\\Git\\bin\\sh.exe'
    // , ['notepad', 'index'], { cwd: __dirname });



    // var interval = null;
    // var t = setTimeout(function(){
    //   interval = setInterval(function(){
      
    //     console.log('Awaiting close : ' + child.spawnargs)
  
    //   }, 1500)
    //   // console.log('Awaiting close : ' + child.spawnargs)

    // }, 0)

    // child.on('close', (code) => {
    //   console.error('Prematurely closed even before promise...')
    // })
    // D:\chess\instances\elixir_01\elxr/.elxr/run-1630002739610/download.bat https://github.com/git-for-windows/git/releases/download/v2.33.0.windows.2/Git-2.33.0.2-64-bit.exe D:\\chess\\instances\\elixir_01\\elxr/Downloads/Git-2.33.0.2-64-bit.exe
    // D:\\chess\\instances\\elixir_01\\elxr/.elxr/run-1630002923584/download.bat https://github.com/git-for-windows/git/releases/download/v2.33.0.windows.2/Git-2.33.0.2-64-bit.exe D:\\chess\\instances\\elixir_01\\elxr/Downloads/Git-2.33.0.2-64-bit.exe
  
    var p = new Promise(function(resolve, reject){
      // console.log(...args)
      const child = spawn(...args);
      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) */ 
            console.log('Error exit not handled.')
          }  );
          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) => {
          // console.log('Proper close was fired')
          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('') )
            }
          }
          // clearInterval(interval)
          if(code !== 0 || opts.haserrors) return reject(logEntry)
          resolve(logEntry)
        });
      }
      else {
        child.unref()
        // clearInterval(interval)
        resolve(true);
      }
    });
    // p.process = child; 
    return p;
}

var prompt = function(choices, label, defaultchoice){
  var choices = choices || [];
  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();
            console.log("resolve is being called");
            resolve(answer) 
          })
        })
      }
    }
    return prompt_interface
  }
  , prompt
}

module.exports = cli