'use strict';

var util = require('./lib/util');

exports = module.exports = gulpRepl;
exports.instances = [];

/**
 * create a readline interface
**/
var repl = require('readline').createInterface({
  input: process.stdin,
  output: process.stdout,
  completer: function onCompletion(line){
    return util.completer(line, exports.instances);
  }
});

/**
 * queue tasks when line is not empty
**/
repl.on('line', function onLine(input){
  var line = input.trim();
  if(!line){ return repl.prompt(); }

  var queue = {
    found: [],
    notFound: line.split(/[ ]+/)
  };

  exports.instances.forEach(function(inst){
    var tasks = util.getQueue(queue.notFound.join(' '), inst.tasks);
    if(tasks.found.length){
      queue.found.push({
        inst: inst,
        tasks: tasks.found
      });
    }
    queue.notFound = tasks.notFound;
  });

  if(queue.notFound.length){
    var plural = queue.notFound.length > 1;
    console.log(' `%s` task%s %s not defined yet',
      queue.notFound.join(', '),
      plural ? 's' : '',
      plural ? 'are' : 'is'
    );
  } else {
    queue.found.forEach(function(found){
      var result = found.inst.runner.apply(found.inst.gulp, found.tasks);
      if(typeof result === 'function'){
        result(); // gulp#4.0
      }
    });
  }

  repl.waitToPrompt(2);
});

/**
 * exit on SIGINT with a timestamp
**/
repl.on('SIGINT', function onSIGINT(){
  process.stdout.write('\n');
  console.log(new Date());
  process.exit(0);
});

var timer;
var write = process.stdout.write;
/**
 * wait for stdout to prompt
**/
repl.waitToPrompt = function(bailAfter){
  bailAfter = bailAfter || Infinity;
  var writes = 0;

  clearTimeout(timer);
  process.stdout.write = (function(stub){
    return (function(/* arguments */){
      stub.apply(process.stdout, arguments);

      clearTimeout(timer);
      if(++writes > bailAfter){
        process.stdout.write = write;
      } else {
        timer = setTimeout(function(){
          process.stdout.write = write;
          repl.prompt();
        }, 500);
      }
    });
  })(process.stdout.write);

  return this;
};

/**
 * add the given gulp instance to the instances array
**/
function gulpRepl(_gulp_){
  var gulp = util.getGulp(_gulp_);

  var inInstances = Boolean(
    exports.instances.filter(function(instance){
      return instance.gulp === gulp;
    }).length
  );
  if(inInstances){ return repl; }

  exports.instances.push({
    gulp: gulp,
    tasks: util.getTasks(gulp),
    runner: gulp.parallel || gulp.start
  });

  return repl;
}

@@ -1276,33 +1276,8 @@
 %0A  %7D
-%0A%0A  repl.waitToPrompt(2);
 %0A%7D);
@@ -1445,634 +1445,8 @@
 );%0A%0A
-var timer;%0Avar write = process.stdout.write;%0A/**%0A * wait for stdout to prompt%0A**/%0Arepl.waitToPrompt = function(bailAfter)%7B%0A  bailAfter = bailAfter %7C%7C Infinity;%0A  var writes = 0;%0A%0A  clearTimeout(timer);%0A  process.stdout.write = (function(stub)%7B%0A    return (function(/* arguments */)%7B%0A      stub.apply(process.stdout, arguments);%0A%0A      clearTimeout(timer);%0A      if(++writes %3E bailAfter)%7B%0A        process.stdout.write = write;%0A      %7D else %7B%0A        timer = setTimeout(function()%7B%0A          process.stdout.write = write;%0A          repl.prompt();%0A        %7D, 500);%0A      %7D%0A    %7D);%0A  %7D)(process.stdout.write);%0A%0A  return this;%0A%7D;%0A%0A
 /**%0A

drop waitToPrompt, only introduces unnecessary complexity