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');

var regPath = 'reg.exe';
if (process.env.SystemRoot) {
  regPath = path.join(process.env.SystemRoot, 'System32', regPath)
}

// 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 reg.exe and callback when it completes
function spawnReg(args, callback) {
  spawn(regPath, args, callback);
}

// 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);
    ChildProcess.spawn(execPath, [], {detached: true});
  });
  app.quit();
}

// Add a protocol registration for this application.
function installProtocol(protocol, callback) {
  var queue = [
    ['HKCU\\Software\\Classes\\' + protocol, '/ve', '/d', 'URL:' + protocol + ' Protocol'],
    ['HKCU\\Software\\Classes\\' + protocol, '/v', 'URL Protocol'],
    ['HKCU\\Software\\Classes\\' + protocol + '\\DefaultIcon', '/ve', '/d', '"' + process.execPath + '",-1'],
    ['HKCU\\Software\\Classes\\' + protocol + '\\shell\\open\\command', '/ve', '/d', '"' + process.execPath + '" --url "%1"']
  ];

  function addToRegistry() {
    if (queue.length === 0) {
      if (callback != null) {
        callback();
      }
    }
    else {
      var args = queue.shift();
      args.unshift('add');
      args.push('/f');
      spawnReg(args, addToRegistry);
    }
  }
  addToRegistry();
}

// Purge the protocol for this application.
function uninstallProtocol(protocol, callback) {
  spawnReg(['delete', 'HKCU\\Software\\Classes\\' + protocol, '/f'], callback);  
}

// Handle squirrel events denoted by --squirrel-* command line arguments.
function handleStartupEvent(protocol, app, squirrelCommand) {
  switch (squirrelCommand) {
    case '--squirrel-install':
      installProtocol(protocol, function() {
        app.exit();
      });
      return true;
    case '--squirrel-updated':
      installProtocol(protocol, function() {
        app.exit();
      });
      return true;
    case '--squirrel-uninstall':
      uninstallProtocol(protocol, function() {
        app.quit();
      });
      return true;
    case '--squirrel-obsolete':
      app.quit();
      return true;
    default:
      // installProtocol(protocol);
      return false;
  }
}

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