var ChildProcess = require('child_process');
var fs = require('fs');
var path = require('path');

var appFolder = path.resolve(process.execPath, '..');
var rootFolder = path.resolve(appFolder, '..');
var binFolder = path.join(rootFolder, 'bin');
var updateDotExe = path.join(rootFolder, 'Update.exe');

// Spawn a command and invoke the callback when it completes with an error
// and the output from standard out.
function spawn(command, args, callback) {
  var stdout = '';

  var spawnedProcess;
  try {
    spawnedProcess = ChildProcess.spawn(command, args);
  }
  catch (error) {
    // Spawn can throw an error
    process.nextTick(function() {
      if (callback != null) {
        callback(error, stdout);
      }
    });
    return;
  }

  spawnedProcess.stdout.on('data', function(data) {
    stdout += data;
  });

  var error = null;
  spawnedProcess.on('error', function(processError) {
    if (error != null) {
      error = processError;
    }
  });
  spawnedProcess.on('close', function(code, signal) {
    if (error != null && code !== 0) {
      error = new Error('Command failed: ' + (signal || code));
    }
    if (error != null) {
      error.code = error.code || code;
      error.stdout = error.stdout || stdout;
    }
    if (callback != null) {
      callback(error, stdout);
    }
  });
}

// Spawn the Update.exe with the given arguments and invoke the callback when
// the command completes.
function spawnUpdate(args, callback) {
  spawn(updateDotExe, args, callback);
}

// Is the Update.exe installed?
function existsSync() {
  return fs.existsSync(updateDotExe);
}

// Restart App.
function restart(app, newVersion) {
  app.once('will-quit', function() {
    var execPath = process.execPath.replace(app.getVersion(), newVersion);
    spawn(execPath, process.execArgv);
  });
  app.quit();
}

exports.spawn = spawnUpdate;
exports.existsSync = existsSync;
exports.restart = restart;
