var sander = require('sander');
var path = require('path');
var spawn = require('child_process').spawn;

module.exports = nodeApp;

function noop() {}

function nodeApp(indir, outdir, options, done) {
  var dir = path.resolve(outdir, '../../../.node-app');
  var pidfile = path.resolve(dir, 'NODE-APP.pid');
  var log = this.log || noop;

  options.pidfile = pidfile;
  options.dir = dir;

  if (typeof options.init === 'function') {
    options.init.call(this, options);
  }

  if (!nodeApp.inited) {
    nodeApp.inited = true;
    process.on('exit', function() {
      if (nodeApp.child) {
        console.log('killing child ' + nodeApp.child.pid);
        nodeApp.child.kill('SIGINT');
      }
      sander.unlinkSync(pidfile);
    });
    if (sander.existsSync(pidfile)) {
      log('\nIt looks like gobble restarted, so I\'m going to try killing the old node app process.');
      var pid = sander.readFileSync(pidfile).toString();
      try {
        process.kill(pid, 'SIGINT');
      } catch (e) {}
    }
  }

  if (sander.existsSync(pidfile)) {
    if (nodeApp.child) {
      console.log('...killing child ' + nodeApp.child.pid);
      nodeApp.child.on('exit', step1);
      nodeApp.child.kill('SIGINT');
    } else step1();
  } else step1();

  function step1() {
    sander.copydirSync(indir).to(dir);
    var exec = options.exec || process.execPath;
    var args = (options.flags || []).concat(path.join('.node-app', options.entry));
    if (Array.isArray(options.appflags)) args = args.concat(options.appflags);
    var opts = {};

    var child = nodeApp.child = spawn(exec, args, opts);
    var started = Date.now();
    var timeout = options.timeout || 1000;
    child.on('exit', function() {
      nodeApp.child = undefined;
      if (Date.now() - started < timeout) {
        console.warn('Your node app exited in less than ' + timeout + 'ms. Something may have gone wrong.');
      }
    });
    child.stdout.on('data', nodeApp.log);
    child.stderr.on('data', nodeApp.log);
    sander.writeFileSync(pidfile, child.pid);
    setTimeout(done, timeout);
  }
}
nodeApp.log = function log(data) { console.log(data.toString()); };

@@ -119,19 +119,22 @@
 s = node
-App
+Server
 ;%0A%0Afunct
@@ -161,19 +161,22 @@
 ion node
-App
+Server
 (indir, 
@@ -206,19 +206,23 @@
 %7B%0A  var 
-dir
+pidfile
  = path.
@@ -233,72 +233,41 @@
 lve(
-outdir, '../../../.node-app');%0A  var pidfile = path.resolve(dir,
+process.cwd(), options.pidfile %7C%7C
  'NO
@@ -343,29 +343,8 @@
 ile;
-%0A  options.dir = dir;
 %0A%0A  
@@ -435,27 +435,30 @@
 %0A  if (!node
-App
+Server
 .inited) %7B%0A 
@@ -464,19 +464,22 @@
     node
-App
+Server
 .inited 
@@ -528,35 +528,38 @@
 %7B%0A      if (node
-App
+Server
 .child) %7B%0A      
@@ -587,35 +587,38 @@
 g child ' + node
-App
+Server
 .child.pid);%0A   
@@ -618,35 +618,38 @@
 d);%0A        node
-App
+Server
 .child.kill('SIG
@@ -1028,27 +1028,30 @@
     if (node
-App
+Server
 .child) %7B%0A  
@@ -1088,27 +1088,30 @@
 ild ' + node
-App
+Server
 .child.pid);
@@ -1117,27 +1117,30 @@
 ;%0A      node
-App
+Server
 .child.on('e
@@ -1159,27 +1159,30 @@
 ;%0A      node
-App
+Server
 .child.kill(
@@ -1256,47 +1256,8 @@
 ) %7B%0A
-    sander.copydirSync(indir).to(dir);%0A
     
@@ -1359,19 +1359,13 @@
 oin(
-'.node-app'
+indir
 , op
@@ -1474,16 +1474,38 @@
 opts = %7B
+%0A      cwd: indir%0A    
 %7D;%0A%0A    
@@ -1516,27 +1516,30 @@
 child = node
-App
+Server
 .child = spa
@@ -1633,16 +1633,41 @@
 %7C 1000;%0A
+    var failed = false;%0A%0A
     chil
@@ -1702,19 +1702,22 @@
     node
-App
+Server
 .child =
@@ -1877,24 +1877,47 @@
 e wrong.');%0A
+        failed = true;%0A
       %7D%0A    
@@ -1944,35 +1944,38 @@
 .on('data', node
-App
+Server
 .log);%0A    child
@@ -1993,27 +1993,30 @@
 'data', node
-App
+Server
 .log);%0A    s
@@ -2071,20 +2071,135 @@
 Timeout(
-done
+function() %7B%0A      if (failed) done(new Error('Your app exited before the timeout expired.'));%0A      else done();%0A    %7D
 , timeou
@@ -2216,11 +2216,14 @@
 node
-App
+Server
 .log

rename function to nodeServer; run in the indir instead of copying to an external path; die if the process exits before timeout