angular.module('gateblu-ui', ['ngMaterial']).config((function(_this) {
  return function($mdThemingProvider) {
    $mdThemingProvider.definePalette('octo-blue', {
      '50': '82bbed',
      '100': '5ea8e8',
      '200': '3b94e3',
      '300': '1f81d6',
      '400': '196bb3',
      '500': '14568f',
      '600': '124b7d',
      '700': '0f406b',
      '800': '0d3659',
      '900': '0a2b47',
      'A100': '6c9aff',
      'A200': '3374ff',
      'A400': '0a58ff',
      'A700': '0047e0',
      'contrastDefaultColor': 'light',
      'contrastDarkColors': ['50', '100', '200', '300', '400', 'A100'],
      'contrastLightColors': void 0
    });
    $mdThemingProvider.theme('default').primaryPalette('octo-blue').accentPalette('green', {
      'default': '500'
    });
    $mdThemingProvider.theme('logs').primaryPalette('green').accentPalette('blue', {
      'default': '500'
    });
    $mdThemingProvider.theme('info').primaryPalette('green').accentPalette('blue', {
      'default': '500'
    });
    $mdThemingProvider.theme('confirm').primaryPalette('red').accentPalette('purple', {
      'default': '500'
    });
    return $mdThemingProvider.theme('warning').primaryPalette('amber').accentPalette('green', {
      'default': '500'
    });
  };
})(this));



var DeviceListController,
  bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };

DeviceListController = (function() {
  function DeviceListController(dependencies) {
    if (dependencies == null) {
      dependencies = {};
    }
    this.onDebugChangeResponse = bind(this.onDebugChangeResponse, this);
    this.rootScope = dependencies.rootScope;
    this.scope = dependencies.scope;
    this.GatebluServiceManager = dependencies.GatebluServiceManager;
    this.DeviceLogService = dependencies.DeviceLogService;
    this.DeviceService = dependencies.DeviceService;
    this.mdDialog = dependencies.mdDialog;
    this.scope.DEBUG_SWITCHING_ACTIVE = true;
    this.scope.getDeviceName = (function(_this) {
      return function(device) {
        if (device.initializing) {
          return '[Initializing...]';
        }
        if (device.name == null) {
          return '[Missing Name]';
        }
        return device.name;
      };
    })(this);
    this.scope.isInDebugMode = (function(_this) {
      return function(device) {
        var ref;
        return (device != null ? (ref = device.env) != null ? ref.DEBUG : void 0 : void 0) != null;
      };
    })(this);
    this.scope.turnOnDebug = (function(_this) {
      return function(device) {
        var debugEnv, query;
        debugEnv = device.connector + "*";
        query = {
          $set: {
            "env.DEBUG": debugEnv
          }
        };
        return _this.DeviceService.updateDangerously(device.uuid, query, _this.onDebugChangeResponse);
      };
    })(this);
    this.scope.turnOffDebug = (function(_this) {
      return function(device) {
        var query;
        query = {
          $unset: {
            "env.DEBUG": ""
          }
        };
        return _this.DeviceService.updateDangerously(device.uuid, query, _this.onDebugChangeResponse);
      };
    })(this);
    this.scope.deleteDevice = (function(_this) {
      return function(device) {
        var alert;
        alert = _this.mdDialog.confirm({
          title: 'Are you sure?',
          content: "This will remove " + device.name + " ~" + device.uuid,
          ok: 'Delete',
          cancel: 'Cancel',
          theme: 'confirm'
        });
        return _this.mdDialog.show(alert).then(function() {
          _this.rootScope.$broadcast('device:unregistering', device);
          return _this.GatebluServiceManager.deleteDevice(device);
        });
      };
    })(this);
    this.scope.stopDevice = (function(_this) {
      return function(device) {
        _this.rootScope.$broadcast('device:stopping', device);
        return _this.GatebluServiceManager.deviceState(device, false);
      };
    })(this);
    this.scope.startDevice = (function(_this) {
      return function(device) {
        _this.rootScope.$broadcast('device:starting', device);
        return _this.GatebluServiceManager.deviceState(device, true);
      };
    })(this);
    this.scope.showDevice = (function(_this) {
      return function(device) {
        var alert;
        alert = _this.mdDialog.alert({
          title: device.name,
          content: device.uuid,
          theme: 'info',
          ok: 'Close'
        });
        return _this.mdDialog.show(alert);
      };
    })(this);
    this.scope.showDeviceLog = (function(_this) {
      return function(device) {
        var ref, ref1;
        if ((ref = _this.scope.deviceHasNewError) != null) {
          ref[device.uuid] = false;
        }
        if ((ref1 = _this.scope.deviceHasNewLog) != null) {
          ref1[device.uuid] = false;
        }
        return _this.rootScope.$broadcast('log:open:device', device);
      };
    })(this);
    this.rootScope.$on('log:device:add', (function(_this) {
      return function($event, entry) {
        var base, base1;
        if ((base = _this.scope).deviceHasNewError == null) {
          base.deviceHasNewError = {};
        }
        _this.scope.deviceHasNewError[entry.uuid] = _this.DeviceLogService.hasError(entry.uuid);
        if ((base1 = _this.scope).deviceHasNewLog == null) {
          base1.deviceHasNewLog = {};
        }
        return _this.scope.deviceHasNewLog[entry.uuid] = !_this.scope.deviceHasNewError[entry.uuid];
      };
    })(this));
  }

  DeviceListController.prototype.onDebugChangeResponse = function(error) {
    var alert, alertObj;
    if (error != null) {
      return console.error(error);
    }
    alertObj = {
      title: 'Restart Service',
      content: "Debug mode changed. Restart the gateblu service by pressing the power button.",
      ok: 'Okay',
      theme: 'warning'
    };
    alert = this.mdDialog.alert(alertObj);
    return this.mdDialog.show(alert);
  };

  return DeviceListController;

})();

angular.module('gateblu-ui').controller('DeviceListController', function($rootScope, $scope, GatebluServiceManager, DeviceLogService, DeviceService, $mdDialog) {
  return new DeviceListController({
    rootScope: $rootScope,
    scope: $scope,
    GatebluServiceManager: GatebluServiceManager,
    DeviceLogService: DeviceLogService,
    DeviceService: DeviceService,
    mdDialog: $mdDialog
  });
});

angular.module('gateblu-ui').controller('DeviceLogController', function($scope, DeviceLogService) {
  return $scope.logs = DeviceLogService.all();
});

angular.module('gateblu-ui').controller('FullscreenController', function($rootScope, $scope) {
  return $scope.broadcast = (function(_this) {
    return function(eventName) {
      return $rootScope.$broadcast(eventName);
    };
  })(this);
});

var LogController;

LogController = (function() {
  function LogController(dependencies) {
    if (dependencies == null) {
      dependencies = {};
    }
    this.scope = dependencies.scope;
    this.rootScope = dependencies.rootScope;
    this.scope.closeLog = (function(_this) {
      return function() {
        return _this.rootScope.$broadcast('log:close');
      };
    })(this);
    this.scope.clearLog = (function(_this) {
      return function() {
        if (_this.scope.deviceUuid != null) {
          _this.rootScope.$broadcast('log:clear:device', _this.scope.deviceUuid);
        }
        if (_this.scope.deviceUuid == null) {
          return _this.rootScope.$broadcast('log:clear');
        }
      };
    })(this);
  }

  return LogController;

})();

angular.module('gateblu-ui').controller('LogController', function($scope, $rootScope) {
  return new LogController({
    scope: $scope,
    rootScope: $rootScope
  });
});

var MainController, _, shell, stringify,
  bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };

_ = require('lodash');

shell = require('shell');

stringify = require('json-stringify-safe');

MainController = (function() {
  function MainController(dependencies) {
    var foundCallback, missingCallback;
    if (dependencies == null) {
      dependencies = {};
    }
    this.setupScope = bind(this.setupScope, this);
    this.waitForConfig = bind(this.waitForConfig, this);
    this.clearFullscreen = bind(this.clearFullscreen, this);
    this.showScreens = bind(this.showScreens, this);
    this.setupRootScope = bind(this.setupRootScope, this);
    this.checkVersions = bind(this.checkVersions, this);
    this.updateDevice = bind(this.updateDevice, this);
    this.rootScope = dependencies.rootScope;
    this.scope = dependencies.scope;
    this.timeout = dependencies.timeout;
    this.GatebluServiceManager = dependencies.GatebluServiceManager;
    this.LogService = dependencies.LogService;
    this.DeviceLogService = dependencies.DeviceLogService;
    this.UpdateService = dependencies.UpdateService;
    this.GatebluBackendInstallerService = dependencies.GatebluBackendInstallerService;
    this.GatebluService = dependencies.GatebluService;
    this.ConfigService = dependencies.ConfigService;
    this.DeviceManagerService = dependencies.DeviceManagerService;
    this.mdDialog = dependencies.mdDialog;
    this.interval = dependencies.interval;
    this.LogService.add('Starting up!', 'info');
    this.setupScope();
    missingCallback = (function(_this) {
      return function() {
        return _this.scope.fullscreen = {
          message: 'Missing Configuration. Will retry in 10 seconds.',
          spinner: false,
          noTimeout: true
        };
      };
    })(this);
    foundCallback = (function(_this) {
      return function() {
        _this.ConfigService.reset();
        _this.clearFullscreen();
        _this.setupRootScope();
        _this.checkVersions();
        _this.interval(function() {
          return _this.checkVersions();
        }, 1000 * 60 * 10);
        return _this.GatebluServiceManager.whoami(function(error, data) {
          if (error == null) {
            return _this.scope.gateblu = data;
          }
        });
      };
    })(this);
    this.ConfigService.waitForMeshbluConfig({
      seconds: 30,
      missingCallback: missingCallback,
      foundCallback: foundCallback
    });
  }

  MainController.prototype.updateDevice = function(device) {
    var filename, ref;
    filename = (ref = device.type) != null ? ref.replace(':', '/') : void 0;
    device.icon_url = "https://icons.octoblu.com/" + filename + ".svg";
    device.background = '#f5f5f5';
    if (device.col_span == null) {
      device.col_span = 1;
    }
    if (device.row_span == null) {
      device.row_span = 1;
    }
    if (device.online === false) {
      device.background = '#e5e5e5';
    }
    return device;
  };

  MainController.prototype.checkVersions = function() {
    return this.UpdateService.checkServiceVersion((function(_this) {
      return function(error, serviceUpdateAvailable, serviceVersion, newServiceVersion) {
        if (error != null) {
          return console.error('Error', error.message);
        }
        return _this.UpdateService.checkUiVersion(function(error, uiUpdateAvailable, uiVersion, newUiVersion) {
          if (error != null) {
            return console.error('Error', error.message);
          }
          return _this.timeout(function() {
            _this.scope.serviceVersion = serviceVersion;
            _this.scope.newServiceVersion = newServiceVersion;
            _this.scope.uiVersion = uiVersion;
            _this.scope.newUiVersion = newUiVersion;
            _this.scope.serviceUpdateAvailable = serviceUpdateAvailable;
            _this.scope.uiUpdateAvailable = uiUpdateAvailable;
            _this.scope.serviceInstallerLink = _this.GatebluServiceManager.getInstallerLink("v" + newServiceVersion);
            return _this.scope.uiInstallerLink = _this.scope.getInstallerLink("v" + newUiVersion);
          }, 0);
        });
      };
    })(this));
  };

  MainController.prototype.setupRootScope = function() {
    this.rootScope.$on("gateblu:connected", (function(_this) {
      return function($event) {
        return _this.LogService.add("Gateblu Connected", 'info');
      };
    })(this));
    this.rootScope.$on('gateblu:claim', (function(_this) {
      return function($event) {
        return _this.GatebluServiceManager.generateSessionToken(function(error, result) {
          if (error != null) {
            return _this.rootScope.$broadcast('error', error);
          }
          return shell.openExternal("https://app.octoblu.com/node-wizard/claim/" + result.uuid + "/" + result.token);
        });
      };
    })(this));
    this.rootScope.$on('gateblu:config', (function(_this) {
      return function($event, config) {
        _this.LogService.add('Gateblu Config Changed', 'info');
        if (typeof _this.configChange === "function") {
          _this.configChange(config);
        }
        _this.scope.gatebluConfig = config;
        return _this.showScreens();
      };
    })(this));
    this.rootScope.$on('gateblu:config:update', (function(_this) {
      return function($event, config) {
        return _this.GatebluServiceManager.updateGatebluConfig(config, function(error) {
          if (error != null) {
            return _this.rootScope.$broadcast('error', error);
          }
          return _this.waitForConfig('online', true, function() {
            return _this.scope.promptToClose();
          });
        });
      };
    })(this));
    this.rootScope.$on('gateblu:device:config', (function(_this) {
      return function($event, config) {
        var device;
        device = _.findWhere(_this.scope.devices, {
          uuid: config.uuid
        });
        if (device == null) {
          return;
        }
        return _.extend(device, config);
      };
    })(this));
    this.rootScope.$on('gateblu:notReady', (function(_this) {
      return function($event, config) {
        _this.LogService.add("Meshblu Authentication Failed", 'error');
        return _this.scope.fullscreen = {
          message: 'Meshblu Authentication Failed'
        };
      };
    })(this));
    this.rootScope.$on("gateblu:disconnected", (function(_this) {
      return function($event) {
        _this.LogService.add("Gateblu Disconnected", 'warning');
        return _this.scope.fullscreen = {
          message: 'Reconnecting to Octoblu...',
          spinner: true
        };
      };
    })(this));
    this.rootScope.$on('gateblu:devices', (function(_this) {
      return function($event, devices) {
        if (devices == null) {
          devices = [];
        }
        _this.LogService.add('Received Device List', 'info');
        _this.scope.devices = _.map(devices, _this.updateDevice);
        return _this.clearFullscreen();
      };
    })(this));
    this.rootScope.$on("device:unregistering", (function(_this) {
      return function($event, device) {
        return _this.fullscreen = {
          message: 'Deleting Device...',
          spinner: true
        };
      };
    })(this));
    this.rootScope.$on("device:unregistered", (function(_this) {
      return function($event, device) {
        var msg;
        msg = device.name + " (~" + device.uuid + ") has been deleted";
        _this.DeviceLogService.add(device.uuid, 'warning', msg);
        _this.LogService.add(msg, 'warning');
        return _this.clearFullscreen();
      };
    })(this));
    this.rootScope.$on('log:open:device', (function(_this) {
      return function($event, device) {
        var uuid;
        uuid = device.uuid.slice(0, 8);
        _this.scope.showLog = true;
        if (device.name != null) {
          _this.scope.logTitle = "\"" + device.name + "\" Log (~" + uuid + "...)";
        }
        if (device.name == null) {
          _this.scope.logTitle = "Device Log (~" + uuid + "...)";
        }
        _this.scope.showingLogForDevice = device.uuid;
        return _this.scope.logLines = _this.DeviceLogService.get(device.uuid);
      };
    })(this));
    this.rootScope.$on('log:device:add', (function(_this) {
      return function($event, entry) {
        if (_this.scope.showingLogForDevice === entry.uuid) {
          return _this.scope.logLines = _this.DeviceLogService.get(entry.uuid);
        }
      };
    })(this));
    this.rootScope.$on('log:close', (function(_this) {
      return function($event) {
        _this.scope.showLog = false;
        return _this.scope.showingLogForDevice = null;
      };
    })(this));
    this.rootScope.$on('log:clear:device', (function(_this) {
      return function($event, uuid) {
        _this.DeviceLogService.clear(uuid);
        return _this.scope.logLines = [];
      };
    })(this));
    this.rootScope.$on('log:clear', (function(_this) {
      return function($event) {
        _this.LogService.clear();
        return _this.scope.logLines = [];
      };
    })(this));
    this.rootScope.$on('error', (function(_this) {
      return function($event, error) {
        return _this.scope.showError(error);
      };
    })(this));
    return this.rootScope.$on('prompt-to-close', (function(_this) {
      return function($event) {
        return _this.scope.promptToClose();
      };
    })(this));
  };

  MainController.prototype.showScreens = function() {
    var message, ref, ref1, uuids;
    uuids = _.pluck(this.scope.devices, 'uuid');
    if (((ref = this.scope.gatebluConfig) != null ? ref.uuid : void 0) == null) {
      this.scope.fullscreen = {
        message: 'Initializing...',
        spinner: true
      };
      return;
    }
    if (((ref1 = this.scope.gatebluConfig) != null ? ref1.owner : void 0) == null) {
      this.scope.fullscreen = {
        buttonTitle: 'Claim Gateblu',
        eventName: 'gateblu:claim',
        claiming: true,
        noTimeout: true,
        menu: true
      };
      return;
    }
    if (_.isEmpty(this.scope.devices)) {
      message = 'No Devices';
      if (!_.isEmpty(this.scope.gatebluConfig.devices)) {
        message = 'No Devices (May be Loading...)';
      }
      this.scope.fullscreen = {
        message: message,
        menu: true,
        spinner: false,
        noTimeout: true
      };
      return;
    }
    return this.clearFullscreen();
  };

  MainController.prototype.clearFullscreen = function() {
    return this.scope.fullscreen = null;
  };

  MainController.prototype.waitForConfig = function(key, value, callback) {
    if (callback == null) {
      callback = function() {};
    }
    return this.configChange = (function(_this) {
      return function(config) {
        if (config[key] === value) {
          return callback();
        }
      };
    })(this);
  };

  MainController.prototype.setupScope = function() {
    this.scope.fullscreen = {
      message: 'Connecting to Octoblu...',
      spinner: true,
      noTimeout: true
    };
    this.scope.showingLogForDevice = null;
    this.scope.showLog = false;
    this.scope.isInstalled = this.GatebluServiceManager.isInstalled();
    this.scope.deviceLogs = {};
    this.scope.devices = [];
    this.scope.deviceUuids = [];
    this.scope.getInstallerLink = (function(_this) {
      return function(version) {
        var baseUrl, filename;
        if (version == null) {
          version = 'latest';
        }
        baseUrl = "https://s3-us-west-2.amazonaws.com/gateblu/gateblu-ui/" + version;
        if (process.platform === 'darwin') {
          filename = 'Gateblu.dmg';
        }
        if (process.platform === 'win32') {
          filename = "GatebluApp-win32-" + process.arch + ".msi";
        }
        return baseUrl + "/" + filename;
      };
    })(this);
    this.scope.showMainLog = (function(_this) {
      return function(device) {
        _this.scope.showLog = true;
        _this.scope.logTitle = 'Gateblu Log';
        return _this.scope.logLines = _this.LogService.all();
      };
    })(this);
    this.scope.listenToDevice = (function(_this) {
      return function(device) {
        return _this.GatebluServiceManager.getLogForDevice(device.uuid);
      };
    })(this);
    this.scope.hardRestartGateblu = (function(_this) {
      return function() {
        var alert;
        alert = _this.mdDialog.confirm({
          title: 'Hard Restart Gateblu',
          content: 'This will stop gateblu service, remove the devices and modules cache, then start gateblu. It will take a few minutes to redownload and configure the devices.',
          ok: 'Hard Restart',
          cancel: 'Cancel',
          theme: 'warning'
        });
        return _this.mdDialog.show(alert).then(function() {
          _this.scope.fullscreen = {
            message: 'Restarting Gateblu',
            spinner: true
          };
          _this.waitForConfig('online', true, function() {
            return _this.clearFullscreen();
          });
          return _this.GatebluServiceManager.hardRestartGateblu(function(error) {
            if (error != null) {
              _this.scope.showError(error);
            }
            return _this.rootScope.$apply();
          });
        });
      };
    })(this);
    this.scope.resetGateblu = (function(_this) {
      return function() {
        var alert;
        alert = _this.mdDialog.confirm({
          title: 'Reset Gateblu',
          content: 'Do you want to reset your Gateblu? This will unregister it from your account and remove all your things.',
          ok: 'Reset',
          cancel: 'Cancel',
          theme: 'warning'
        });
        return _this.mdDialog.show(alert).then(function() {
          _this.scope.fullscreen = {
            message: 'Resetting Gateblu',
            spinner: true
          };
          _this.waitForConfig('online', true, function() {
            if (typeof error === "undefined" || error === null) {
              return _this.scope.promptToClose();
            }
          });
          return _this.GatebluServiceManager.resetGateblu(function(error) {
            if (error != null) {
              _this.scope.showError(error);
            }
            return _this.rootScope.$apply();
          });
        });
      };
    })(this);
    this.scope.promptToClose = (function(_this) {
      return function() {
        var alert;
        alert = _this.mdDialog.alert({
          title: 'Close Gateblu',
          content: "Please quit Gateblu and reopen.",
          ok: 'Okay',
          theme: 'warning'
        });
        return _this.mdDialog.show(alert).then(function() {
          return _this.fullscreen = {
            message: 'Close Application'
          };
        });
      };
    })(this);
    this.scope.showError = (function(_this) {
      return function(error) {
        var alert, error1, errorMessage;
        try {
          errorMessage = error.toString();
        } catch (error1) {
          errorMessage = JSON.stringify(error);
        }
        _this.LogService.add(errorMessage, 'error');
        alert = _this.mdDialog.alert({
          title: 'Error',
          content: errorMessage,
          ok: 'Okay',
          theme: 'warning'
        });
        return _this.mdDialog.show(alert);
      };
    })(this);
    this.scope.startService = (function(_this) {
      return function() {
        _this.scope.fullscreen = {
          message: "Starting Service...",
          spinner: true,
          waitForConfig: true
        };
        _this.waitForConfig('online', true, function() {
          return _this.clearFullscreen();
        });
        return _this.GatebluServiceManager.stopAndStartService(function(error) {
          if (error != null) {
            return _this.LogService.add(error, 'error');
          }
        });
      };
    })(this);
    this.scope.stopService = (function(_this) {
      return function() {
        _this.scope.fullscreen = {
          message: "Stopping Service...",
          spinner: true,
          waitForConfig: true
        };
        _this.waitForConfig('online', false, function() {
          return _this.clearFullscreen();
        });
        return _this.GatebluServiceManager.stopService(function(error) {
          if (error != null) {
            return _this.LogService.add(error, 'error');
          }
        });
      };
    })(this);
    this.scope.toggleInfo = (function(_this) {
      return function() {
        return _this.scope.showInfo = !_this.scope.showInfo;
      };
    })(this);
    this.scope.hideChangeNoticeAction = (function(_this) {
      return function() {
        return _this.scope.hideChangeNotice = true;
      };
    })(this);
    this.scope.$watch('fullscreen', (function(_this) {
      return function() {};
    })(this));
    return this.scope.$watch('devices', (function(_this) {
      return function() {
        return _this.showScreens();
      };
    })(this));
  };

  return MainController;

})();

angular.module('gateblu-ui').controller('MainController', function($rootScope, $scope, $timeout, $interval, GatebluServiceManager, ConfigService, LogService, DeviceLogService, UpdateService, GatebluBackendInstallerService, GatebluService, DeviceManagerService, $mdDialog) {
  return new MainController({
    rootScope: $rootScope,
    scope: $scope,
    timeout: $timeout,
    interval: $interval,
    mdDialog: $mdDialog,
    GatebluServiceManager: GatebluServiceManager,
    LogService: LogService,
    DeviceLogService: DeviceLogService,
    UpdateService: UpdateService,
    GatebluBackendInstallerService: GatebluBackendInstallerService,
    GatebluService: GatebluService,
    DeviceManagerService: DeviceManagerService,
    ConfigService: ConfigService
  });
});

var $, devTools, ipc, sendIpcMessage;

ipc = require('ipc');

$ = require('jquery');

sendIpcMessage = function(message, callback) {
  return ipc.send('asynchronous-message', message, (function(_this) {
    return function(response) {
      return callback(response.error, response.message);
    };
  })(this));
};

devTools = function() {
  return {
    restrict: 'C',
    link: (function(_this) {
      return function(scope, element, attrs) {
        return $(element).click(function(event) {
          event.preventDefault();
          return sendIpcMessage({
            topic: 'dev-tools',
            link: attrs.href
          });
        });
      };
    })(this)
  };
};

angular.module('gateblu-ui').directive("devTools", devTools);

angular.module('gateblu-ui').directive('deviceList', function() {
  return {
    restrict: 'E',
    scope: {
      devices: '='
    },
    templateUrl: 'pages/device-list.html',
    controller: 'DeviceListController'
  };
});

var DropMeshbluJson,
  bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };

DropMeshbluJson = (function() {
  function DropMeshbluJson() {
    this.getFromFile = bind(this.getFromFile, this);
    this.getFromData = bind(this.getFromData, this);
    this.onData = bind(this.onData, this);
    this.parseData = bind(this.parseData, this);
    this.validate = bind(this.validate, this);
    this.link = bind(this.link, this);
  }

  DropMeshbluJson.prototype.link = function(scope, element) {
    var holder;
    this.scope = scope;
    holder = element[0];
    holder.ondragover = function() {
      return false;
    };
    holder.ondragleave = function() {
      return false;
    };
    holder.ondragend = function() {
      return false;
    };
    return holder.ondrop = (function(_this) {
      return function(event) {
        var file, item;
        event.preventDefault();
        event.stopPropagation();
        file = event.dataTransfer.files[0];
        item = event.dataTransfer.items[0];
        if (file != null) {
          return _this.getFromFile(file, _this.onData);
        }
        if (item != null) {
          return _this.getFromData(item, _this.onData);
        }
      };
    })(this);
  };

  DropMeshbluJson.prototype.validate = function(data) {
    if (data == null) {
      return false;
    }
    if (data.uuid == null) {
      return false;
    }
    if (data.token == null) {
      return false;
    }
    return true;
  };

  DropMeshbluJson.prototype.parseData = function(rawData) {
    try {
      return JSON.parse(rawData);
    } catch (undefined) {}
  };

  DropMeshbluJson.prototype.onData = function(error, data) {
    if (!this.validate(data)) {
      return this.scope.$emit('error', 'Invalid Meshblu Config');
    }
    return this.scope.$emit('gateblu:config:update', data);
  };

  DropMeshbluJson.prototype.getFromData = function(item, callback) {
    return item.getAsString((function(_this) {
      return function(rawMeshbluJson) {
        return callback(null, _this.parseData(rawMeshbluJson));
      };
    })(this));
  };

  DropMeshbluJson.prototype.getFromFile = function(file, callback) {
    var fileReader;
    fileReader = new FileReader();
    fileReader.addEventListener('load', (function(_this) {
      return function(event) {
        return callback(null, _this.parseData(event.target.result));
      };
    })(this));
    return fileReader.readAsText(file);
  };

  return DropMeshbluJson;

})();

angular.module('gateblu-ui').directive('dropMeshbluJson', function() {
  return {
    restrict: 'A',
    link: function() {
      var ref;
      return (ref = new DropMeshbluJson()).link.apply(ref, arguments);
    }
  };
});

var $, externalLink, ipc, sendIpcMessage;

ipc = require('ipc');

$ = require('jquery');

sendIpcMessage = function(message, callback) {
  return ipc.send('asynchronous-message', message, (function(_this) {
    return function(response) {
      return callback(response.error, response.message);
    };
  })(this));
};

externalLink = function() {
  return {
    restrict: 'C',
    link: (function(_this) {
      return function(scope, element, attrs) {
        return $(element).click(function(event) {
          event.preventDefault();
          return sendIpcMessage({
            topic: 'external-link',
            link: attrs.href
          });
        });
      };
    })(this)
  };
};

angular.module('gateblu-ui').directive("externalLink", externalLink);

angular.module('gateblu-ui').directive('fullScreenMessage', function() {
  return {
    restrict: 'E',
    scope: {
      message: '=',
      buttonTitle: '=',
      eventName: '=',
      spinner: '='
    },
    templateUrl: 'pages/full-screen-message.html',
    controller: 'FullscreenController'
  };
});

angular.module('gateblu-ui').directive('log', function() {
  return {
    restrict: 'E',
    templateUrl: 'pages/log.html',
    scope: {
      title: '=',
      logLines: '=',
      deviceUuid: '='
    },
    controller: 'LogController'
  };
});

angular.module('gateblu-ui').filter("formatLogs", function() {
  var stringify;
  stringify = function(line) {
    var error, message;
    message = line.message;
    if (!_.isString(message)) {
      try {
        message = JSON.stringify(message).toString();
      } catch (error) {

      }
    }
    return line.timestamp + " - " + message;
  };
  return function(lines) {
    return _.map(lines, stringify).join('\n');
  };
});

var Gateblu,
  bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };

Gateblu = (function() {
  function Gateblu(uuid, token) {
    this.uuid = uuid;
    this.token = token;
    this.start = bind(this.start, this);
  }

  Gateblu.prototype.start = function() {};

  return Gateblu;

})();

angular.module('gateblu-ui').constant('Gateblu', Gateblu);

var ConfigService, PROGRAMFILES, fs, jsonfile, request,
  bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };

fs = require('fs-extra');

jsonfile = require('jsonfile');

request = require('request');

PROGRAMFILES = process.env['PROGRAMFILES(X86)'] || process.env['PROGRAMFILES'];

ConfigService = (function() {
  function ConfigService(arg) {
    this.interval = arg.interval;
    this.waitForMeshbluConfig = bind(this.waitForMeshbluConfig, this);
    this.getServiceDir = bind(this.getServiceDir, this);
    this.getServicePackagePath = bind(this.getServicePackagePath, this);
    this.getSupportPath = bind(this.getSupportPath, this);
    this.loadUIPackageJson = bind(this.loadUIPackageJson, this);
    this.loadServicePackageJson = bind(this.loadServicePackageJson, this);
    this.loadMeshbluConfig = bind(this.loadMeshbluConfig, this);
    this.meshbluConfigExists = bind(this.meshbluConfigExists, this);
    this.reset = bind(this.reset, this);
    this.meshbluConfigFile = this.getSupportPath('meshblu.json');
    this.reset();
  }

  ConfigService.prototype.reset = function() {
    this.servicePackageJson = this.loadServicePackageJson();
    this.uiPackageJson = this.loadUIPackageJson();
    return this.meshbluConfig = this.loadMeshbluConfig();
  };

  ConfigService.prototype.meshbluConfigExists = function() {
    return fs.existsSync(this.meshbluConfigFile);
  };

  ConfigService.prototype.loadMeshbluConfig = function() {
    if (this.meshbluConfigExists()) {
      return jsonfile.readFileSync(this.meshbluConfigFile, {
        throws: false
      });
    }
  };

  ConfigService.prototype.loadServicePackageJson = function() {
    return jsonfile.readFileSync(this.getServicePackagePath(), {
      throws: false
    });
  };

  ConfigService.prototype.loadUIPackageJson = function() {
    var filename;
    filename = path.resolve(__dirname + '/package.json');
    return jsonfile.readFileSync(filename, {
      throws: false
    });
  };

  ConfigService.prototype.getSupportPath = function(fileOrPath) {
    if (process.platform === 'darwin') {
      return process.env.HOME + "/Library/Application Support/GatebluService/" + fileOrPath;
    }
    if (process.platform === 'win32') {
      return process.env.LOCALAPPDATA + "\\Octoblu\\GatebluService\\" + fileOrPath;
    }
    return "./" + filePath;
  };

  ConfigService.prototype.getServicePackagePath = function() {
    if (process.platform === 'darwin') {
      return (this.getServiceDir()) + "/package.json";
    }
    if (process.platform === 'win32') {
      return (this.getServiceDir()) + "\\package.json";
    }
    return (this.getServiceDir()) + "/package.json";
  };

  ConfigService.prototype.getServiceDir = function() {
    if (process.platform === 'darwin') {
      return "/Library/Octoblu/GatebluService";
    }
    if (process.platform === 'win32') {
      return PROGRAMFILES + "\\Octoblu\\GatebluService";
    }
    return '.';
  };

  ConfigService.prototype.waitForMeshbluConfig = function(arg) {
    var _foundCallback, foundCallback, intervalId, missingCallback, seconds;
    seconds = arg.seconds, missingCallback = arg.missingCallback, foundCallback = arg.foundCallback;
    if (seconds == null) {
      seconds = 10;
    }
    _foundCallback = (function(_this) {
      return function() {
        _this.interval.cancel(intervalId);
        return foundCallback();
      };
    })(this);
    if (this.meshbluConfigExists()) {
      return _foundCallback();
    }
    missingCallback();
    return intervalId = this.interval((function(_this) {
      return function() {
        if (_this.meshbluConfigExists()) {
          return _foundCallback();
        }
        return missingCallback();
      };
    })(this), 1000 * seconds);
  };

  return ConfigService;

})();

angular.module('gateblu-ui').service('ConfigService', function($interval) {
  return new ConfigService({
    interval: $interval
  });
});

var DeviceLogService, _,
  bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };

_ = require('lodash');

DeviceLogService = (function() {
  function DeviceLogService($rootScope) {
    this.clearAll = bind(this.clearAll, this);
    this.clear = bind(this.clear, this);
    this.get = bind(this.get, this);
    this.hasError = bind(this.hasError, this);
    this.addRaw = bind(this.addRaw, this);
    this.addGatebluLogMessage = bind(this.addGatebluLogMessage, this);
    this.add = bind(this.add, this);
    this.logs = {};
    this.rootScope = $rootScope;
    this.MAX_LOG_LINES = 100;
  }

  DeviceLogService.prototype.add = function(uuid, type, log) {
    var entry, message;
    message = log;
    try {
      if (!_.isString(log)) {
        message = JSON.stringify(log).toString();
      }
    } catch (undefined) {}
    entry = {
      type: type,
      message: message,
      timestamp: new Date(),
      uuid: uuid,
      rawMessage: log
    };
    return this.addRaw(entry);
  };

  DeviceLogService.prototype.addGatebluLogMessage = function(message) {
    var entry, ref, type;
    if (message == null) {
      return;
    }
    if (message.deviceUuid == null) {
      return;
    }
    type = (function() {
      switch (message.state) {
        case 'stderr':
          return 'error';
        case 'stdout':
        case 'stop':
          return 'debug';
        default:
          return 'info';
      }
    })();
    entry = {
      type: type,
      message: (ref = message.message) != null ? ref : message.workflow,
      timestamp: new Date(),
      uuid: message.deviceUuid,
      state: message.state,
      rawMessage: message
    };
    return this.addRaw(entry);
  };

  DeviceLogService.prototype.addRaw = function(entry) {
    var base, name;
    if ((base = this.logs)[name = entry.uuid] == null) {
      base[name] = [];
    }
    this.logs[entry.uuid].unshift(entry);
    this.logs[entry.uuid] = _.take(this.logs[entry.uuid], this.MAX_LOG_LINES);
    return this.rootScope.$broadcast('log:device:add', entry);
  };

  DeviceLogService.prototype.hasError = function(uuid) {
    return _.any(this.logs[uuid], {
      type: 'error'
    });
  };

  DeviceLogService.prototype.get = function(uuid) {
    return this.logs[uuid];
  };

  DeviceLogService.prototype.clear = function(uuid) {
    return this.logs[uuid] = [];
  };

  DeviceLogService.prototype.clearAll = function() {
    return this.logs = {};
  };

  return DeviceLogService;

})();

angular.module('gateblu-ui').service('DeviceLogService', function($rootScope) {
  return new DeviceLogService($rootScope);
});

var DeviceManagerService,
  bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };

DeviceManagerService = (function() {
  function DeviceManagerService(dependencies) {
    if (dependencies == null) {
      dependencies = {};
    }
    this.stopDevice = bind(this.stopDevice, this);
    this.startDevice = bind(this.startDevice, this);
    this.removeDevice = bind(this.removeDevice, this);
    this.broadcast = bind(this.broadcast, this);
    this.addDevice = bind(this.addDevice, this);
    this.rootScope = dependencies.rootScope;
    this.devices = [];
  }

  DeviceManagerService.prototype.addDevice = function(device, callback) {
    if (callback == null) {
      callback = function() {};
    }
    this.devices.push(device);
    this.broadcast();
    return callback();
  };

  DeviceManagerService.prototype.broadcast = function() {
    this.devices = _.uniq(this.devices, 'uuid');
    if (!_.isArray(this.devices)) {
      this.devices = [];
    }
    this.rootScope.$emit('gateblu:devices', this.devices);
    return this.rootScope.$apply();
  };

  DeviceManagerService.prototype.removeDevice = function(device, callback) {
    if (callback == null) {
      callback = function() {};
    }
    this.devices = _.reject(this.devices, {
      uuid: device.uuid
    });
    this.broadcast();
    return callback();
  };

  DeviceManagerService.prototype.startDevice = function(device, callback) {
    if (callback == null) {
      callback = function() {};
    }
    return callback();
  };

  DeviceManagerService.prototype.stopDevice = function(device, callback) {
    if (callback == null) {
      callback = function() {};
    }
    return callback();
  };

  return DeviceManagerService;

})();

angular.module('gateblu-ui').service('DeviceManagerService', function($rootScope) {
  return new DeviceManagerService({
    rootScope: $rootScope
  });
});

var DeviceService, MeshbluHttp,
  bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };

MeshbluHttp = require('meshblu-http');

DeviceService = (function() {
  function DeviceService(dependencies) {
    if (dependencies == null) {
      dependencies = {};
    }
    this.updateDangerously = bind(this.updateDangerously, this);
    this.rootScope = dependencies.rootScope;
    this.ConfigService = dependencies.ConfigService;
    this.meshbluHttp = new MeshbluHttp(this.ConfigService.meshbluConfig);
    this.devices = [];
  }

  DeviceService.prototype.updateDangerously = function(uuid, query, callback) {
    if (callback == null) {
      callback = function() {};
    }
    if (!query) {
      return console.error('invalid query');
    }
    return this.meshbluHttp.updateDangerously(uuid, query, callback);
  };

  return DeviceService;

})();

angular.module('gateblu-ui').service('DeviceService', function($rootScope, ConfigService) {
  return new DeviceService({
    rootScope: $rootScope,
    ConfigService: ConfigService
  });
});

var GatebluBackendInstallerService, async,
  bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };

async = require('async');

GatebluBackendInstallerService = (function() {
  function GatebluBackendInstallerService(dependencies) {
    this.dependencies = dependencies != null ? dependencies : {};
    this.install = bind(this.install, this);
  }

  GatebluBackendInstallerService.prototype.install = function(callback) {
    if (callback == null) {
      callback = function() {};
    }
    return callback();
  };

  return GatebluBackendInstallerService;

})();

angular.module('gateblu-ui').service('GatebluBackendInstallerService', function($q, $rootScope, $location) {
  return new GatebluBackendInstallerService({
    $q: $q,
    $rootscope: $rootScope,
    $location: $location
  });
});

var GatebluServiceManager, MeshbluHttp, async, debug, exec, fsExtra, path,
  bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };

MeshbluHttp = require('meshblu-http');

async = require('async');

path = require('path');

debug = require('debug')('gateblu-ui:GatebluService');

fsExtra = require('fs-extra');

exec = require('child_process').exec;

GatebluServiceManager = (function() {
  function GatebluServiceManager(dependencies) {
    if (dependencies == null) {
      dependencies = {};
    }
    this.waitForLog = bind(this.waitForLog, this);
    this.generateSessionToken = bind(this.generateSessionToken, this);
    this.hardRestartGateblu = bind(this.hardRestartGateblu, this);
    this.resetGateblu = bind(this.resetGateblu, this);
    this.updateGatebluConfig = bind(this.updateGatebluConfig, this);
    this.unregisterGateblu = bind(this.unregisterGateblu, this);
    this.deleteDevice = bind(this.deleteDevice, this);
    this.emit = bind(this.emit, this);
    this.updateGatebluConfigFile = bind(this.updateGatebluConfigFile, this);
    this.removeGatebluConfig = bind(this.removeGatebluConfig, this);
    this.removeDeviceAndTmp = bind(this.removeDeviceAndTmp, this);
    this.deviceState = bind(this.deviceState, this);
    this.stopService = bind(this.stopService, this);
    this.startService = bind(this.startService, this);
    this.stopAndStartService = bind(this.stopAndStartService, this);
    this.getConfigPath = bind(this.getConfigPath, this);
    this.getSupportPath = bind(this.getSupportPath, this);
    this.getInstallerLink = bind(this.getInstallerLink, this);
    this.isInstalled = bind(this.isInstalled, this);
    this.whoami = bind(this.whoami, this);
    this.rootScope = dependencies.rootScope;
    this.http = dependencies.http;
    this.LogService = dependencies.LogService;
    this.DeviceService = dependencies.DeviceService;
    this.DeviceLogService = dependencies.DeviceLogService;
    this.ConfigService = dependencies.ConfigService;
    this.meshbluHttp = new MeshbluHttp(this.ConfigService.meshbluConfig);
  }

  GatebluServiceManager.prototype.whoami = function(callback) {
    if (callback == null) {
      callback = function() {};
    }
    return this.meshbluHttp.whoami((function(_this) {
      return function(error, data) {
        if (error != null) {
          return callback(error);
        }
        return callback(null, data);
      };
    })(this));
  };

  GatebluServiceManager.prototype.isInstalled = function() {
    return !_.isEmpty(this.ConfigService.servicePackageJson);
  };

  GatebluServiceManager.prototype.getInstallerLink = function(version) {
    var baseUrl, filename;
    if (version == null) {
      version = 'latest';
    }
    baseUrl = "https://s3-us-west-2.amazonaws.com/gateblu/gateblu-service/" + version;
    if (process.platform === 'darwin') {
      filename = 'GatebluService.dmg';
    }
    if (process.platform === 'win32') {
      filename = "GatebluService-win32-" + process.arch + ".msi";
    }
    return baseUrl + "/" + filename;
  };

  GatebluServiceManager.prototype.getSupportPath = function(fileOrPath) {
    if (process.platform === 'darwin') {
      return process.env.HOME + "/Library/Application Support/GatebluService/" + fileOrPath;
    }
    if (process.platform === 'win32') {
      return process.env.LOCALAPPDATA + "\\Octoblu\\GatebluService\\" + fileOrPath;
    }
    return "./" + filePath;
  };

  GatebluServiceManager.prototype.getConfigPath = function() {
    return this.getSupportPath("meshblu.json");
  };

  GatebluServiceManager.prototype.stopAndStartService = function(callback) {
    if (callback == null) {
      callback = function() {};
    }
    return this.stopService((function(_this) {
      return function(error) {
        return _this.startService(function(error) {
          if (error != null) {
            return callback(error);
          }
          return callback();
        });
      };
    })(this));
  };

  GatebluServiceManager.prototype.startService = function(callback) {
    if (callback == null) {
      callback = function() {};
    }
    this.LogService.add("Starting Service", 'info');
    if (process.platform === 'darwin') {
      return exec('/bin/launchctl load /Library/LaunchAgents/com.octoblu.GatebluService.plist', (function(_this) {
        return function(error, stdout, stdin) {
          if (error != null) {
            return callback(error);
          }
          return callback();
        };
      })(this));
    }
    if (process.platform === 'win32') {
      return exec("start \"GatebluServiceTray\" \"" + PROGRAMFILES + "\\Octoblu\\GatebluService\\GatebluServiceTray.exe\"", (function(_this) {
        return function(error, stdout, stdin) {
          if (error != null) {
            return callback(error);
          }
          return callback();
        };
      })(this));
    }
    return callback(new Error("Unsupported Operating System"));
  };

  GatebluServiceManager.prototype.stopService = function(callback) {
    if (callback == null) {
      callback = function() {};
    }
    this.LogService.add("Stopping Service", 'info');
    if (process.platform === 'darwin') {
      return exec('/bin/launchctl unload /Library/LaunchAgents/com.octoblu.GatebluService.plist', (function(_this) {
        return function(error, stdout, stdin) {
          if (error != null) {
            return callback(error);
          }
          return callback();
        };
      })(this));
    }
    if (process.platform === 'win32') {
      return exec('taskkill /t /f /im GatebluServiceTray.exe', (function(_this) {
        return function(error, stdout, stdin) {
          if (error != null) {
            return callback(error);
          }
          return callback();
        };
      })(this));
    }
    return callback(new Error("Unsupported Operating System"));
  };

  GatebluServiceManager.prototype.deviceState = function(device, state, callback) {
    var events;
    if (callback == null) {
      callback = function() {};
    }
    events = [
      (function(_this) {
        return function(callback) {
          return _this.meshbluHttp.update(device.uuid, {
            stop: !state
          }, callback);
        };
      })(this), (function(_this) {
        return function(callback) {
          return _this.stopService(function() {
            return callback();
          });
        };
      })(this), (function(_this) {
        return function(callback) {
          return _this.startService(function() {
            return callback();
          });
        };
      })(this)
    ];
    return async.series(events, (function(_this) {
      return function(error) {
        if (error != null) {
          return callback(error);
        }
        return callback();
      };
    })(this));
  };

  GatebluServiceManager.prototype.removeDeviceAndTmp = function(callback) {
    var directories;
    if (callback == null) {
      callback = function() {};
    }
    directories = [this.ConfigService.getSupportPath('tmp')];
    return async.each(directories, fsExtra.emptyDir, callback);
  };

  GatebluServiceManager.prototype.removeGatebluConfig = function(callback) {
    if (callback == null) {
      callback = function() {};
    }
    this.LogService.add('Removing Gateblu Config', 'info');
    return fsExtra.unlink(this.ConfigService.meshbluConfigFile, (function(_this) {
      return function(error) {
        return callback();
      };
    })(this));
  };

  GatebluServiceManager.prototype.updateGatebluConfigFile = function(config, callback) {
    if (callback == null) {
      callback = function() {};
    }
    this.LogService.add('Updating Gateblu Config', 'info');
    return fsExtra.writeJson(this.ConfigService.meshbluConfigFile, config, callback);
  };

  GatebluServiceManager.prototype.emit = function(event, data) {
    this.rootScope.$broadcast(event, data);
    return this.rootScope.$apply();
  };

  GatebluServiceManager.prototype.deleteDevice = function(device) {
    var pullQuery, uuid;
    uuid = this.ConfigService.meshbluConfig.uuid;
    pullQuery = {
      $pull: {
        'devices': {
          uuid: device.uuid
        }
      }
    };
    return this.meshbluHttp.updateDangerously(uuid, pullQuery, (function(_this) {
      return function(error) {
        if (error != null) {
          return _this.emit('error', error);
        }
        return _this.meshbluHttp.unregister(device, function(error) {
          if (error != null) {
            return _this.emit('error', error);
          }
          return _this.emit('device:unregistered', device);
        });
      };
    })(this));
  };

  GatebluServiceManager.prototype.unregisterGateblu = function(callback) {
    if (callback == null) {
      callback = function() {};
    }
    return this.meshbluHttp.unregister(this.ConfigService.meshbluConfig, callback);
  };

  GatebluServiceManager.prototype.updateGatebluConfig = function(config, callback) {
    var events;
    if (callback == null) {
      callback = function() {};
    }
    this.LogService.add('Update Gateblu Config', 'info');
    events = [
      (function(_this) {
        return function(callback) {
          return _this.stopService(function() {
            return callback();
          });
        };
      })(this), (function(_this) {
        return function(callback) {
          return _this.updateGatebluConfigFile(config, callback);
        };
      })(this), (function(_this) {
        return function(callback) {
          return _this.startService(function() {
            return callback();
          });
        };
      })(this)
    ];
    return async.series(events, (function(_this) {
      return function(error) {
        _this.LogService.add('Gateblu Config Updated', 'info');
        if (error != null) {
          return callback(error);
        }
        return callback();
      };
    })(this));
  };

  GatebluServiceManager.prototype.resetGateblu = function(callback) {
    var events;
    if (callback == null) {
      callback = function() {};
    }
    this.LogService.add('Resetting Gateblu', 'warning');
    events = [
      (function(_this) {
        return function(callback) {
          if (callback == null) {
            callback = function() {};
          }
          return _this.stopService(function() {
            return callback();
          });
        };
      })(this), this.unregisterGateblu, this.removeDeviceAndTmp, this.removeGatebluConfig, (function(_this) {
        return function(callback) {
          if (callback == null) {
            callback = function() {};
          }
          return _this.startService(function() {
            return callback();
          });
        };
      })(this)
    ];
    return async.series(events, (function(_this) {
      return function(error) {
        _this.LogService.add('Reset Gateblu', 'info');
        if (error != null) {
          return callback(error);
        }
        return callback();
      };
    })(this));
  };

  GatebluServiceManager.prototype.hardRestartGateblu = function(callback) {
    var events;
    if (callback == null) {
      callback = function() {};
    }
    this.LogService.add('Hard restart Gateblu', 'warning');
    events = [
      (function(_this) {
        return function(callback) {
          if (callback == null) {
            callback = function() {};
          }
          return _this.stopService(function() {
            return callback();
          });
        };
      })(this), this.removeDeviceAndTmp, (function(_this) {
        return function(callback) {
          if (callback == null) {
            callback = function() {};
          }
          return _this.startService(function() {
            return callback();
          });
        };
      })(this)
    ];
    return async.series(events, (function(_this) {
      return function(error) {
        if (error != null) {
          return callback(error);
        }
        _this.LogService.add('Successfully restarted Gateblu', 'info');
        return callback();
      };
    })(this));
  };

  GatebluServiceManager.prototype.generateSessionToken = function(callback) {
    var uuid;
    if (callback == null) {
      callback = function() {};
    }
    uuid = this.ConfigService.meshbluConfig.uuid;
    return this.meshbluHttp.generateAndStoreToken(uuid, (function(_this) {
      return function(error, result) {
        if (error != null) {
          return callback(error);
        }
        return callback(null, result);
      };
    })(this));
  };

  GatebluServiceManager.prototype.waitForLog = function(path, callback) {
    if (callback == null) {
      callback = function() {};
    }
    return fsExtra.exists(path, (function(_this) {
      return function(exists) {
        if (!exists) {
          return _.delay(_this.waitForLog, 1000, path, callback);
        }
        return callback();
      };
    })(this));
  };

  return GatebluServiceManager;

})();

angular.module('gateblu-ui').service('GatebluServiceManager', function($rootScope, $http, LogService, DeviceLogService, ConfigService) {
  return new GatebluServiceManager({
    rootScope: $rootScope,
    http: $http,
    LogService: LogService,
    DeviceLogService: DeviceLogService,
    ConfigService: ConfigService
  });
});

var Gateblu, GatebluService, _,
  bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };

_ = require('lodash');

Gateblu = require('gateblu');

GatebluService = (function() {
  function GatebluService(dependencies) {
    if (dependencies == null) {
      dependencies = {};
    }
    this.broadcast = bind(this.broadcast, this);
    this.onMessage = bind(this.onMessage, this);
    this.whenConfigExists = bind(this.whenConfigExists, this);
    this.start = bind(this.start, this);
    this.rootScope = dependencies.rootScope;
    this.http = dependencies.http;
    this.ConfigService = dependencies.ConfigService;
    this.DeviceLogService = dependencies.DeviceLogService;
    this.DeviceManagerService = dependencies.DeviceManagerService;
  }

  GatebluService.prototype.start = function() {
    var meshbluConfig;
    this.ConfigService.reset();
    meshbluConfig = _.clone(this.ConfigService.meshbluConfig);
    meshbluConfig.auto_set_online = false;
    this.gateblu = new Gateblu(meshbluConfig, this.DeviceManagerService);
    this.gateblu.on('error', (function(_this) {
      return function(error) {
        if (error != null) {
          return _this.broadcast('error', error);
        }
      };
    })(this));
    this.gateblu.on('ready', (function(_this) {
      return function() {
        _this.broadcast('gateblu:connected');
        return _this.gateblu.whoami(function(error, config) {
          if (error != null) {
            return _this.broadcast('error', error);
          }
          return _this.broadcast('gateblu:config', config);
        });
      };
    })(this));
    this.gateblu.on('config', (function(_this) {
      return function(config) {
        _this.broadcast('gateblu:config', config);
        return _this.broadcast('gateblu:refreshDevices', {
          deviceUuids: _.pluck(config.devices, 'uuid')
        });
      };
    })(this));
    this.gateblu.on('refreshDevices', (function(_this) {
      return function(data) {
        return _this.broadcast('gateblu:refreshDevices', data);
      };
    })(this));
    this.gateblu.on('disconnected', (function(_this) {
      return function(error) {
        return _this.broadcast('gateblu:disconnected', error);
      };
    })(this));
    this.gateblu.on('notReady', (function(_this) {
      return function(error) {
        return _this.broadcast('gateblu:notReady', error);
      };
    })(this));
    this.gateblu.on('device:config', (function(_this) {
      return function(config) {
        return _this.broadcast('gateblu:device:config', config);
      };
    })(this));
    this.gateblu.on('message', this.onMessage);
    return this.gateblu.on('device:message', (function(_this) {
      return function(message) {
        return _this.broadcast('gateblu:device:message', message);
      };
    })(this));
  };

  GatebluService.prototype.whenConfigExists = function(callback) {
    if (callback == null) {
      callback = function() {};
    }
    if (this.ConfigService.meshbluConfigExists()) {
      return callback();
    }
    return _.delay(this.whenConfigExists, 2000, callback);
  };

  GatebluService.prototype.onMessage = function(message) {
    var payload, topic;
    this.broadcast('gateblu:message', message);
    payload = message.payload, topic = message.topic;
    if (topic !== 'gateblu_log') {
      return;
    }
    return this.DeviceLogService.addGatebluLogMessage(payload);
  };

  GatebluService.prototype.broadcast = function(event, data) {
    this.rootScope.$broadcast(event, data);
    return this.rootScope.$apply();
  };

  return GatebluService;

})();

angular.module('gateblu-ui').service('GatebluService', function($rootScope, $http, ConfigService, DeviceManagerService, DeviceLogService) {
  var gatebluService;
  gatebluService = new GatebluService({
    rootScope: $rootScope,
    http: $http,
    ConfigService: ConfigService,
    DeviceLogService: DeviceLogService,
    DeviceManagerService: DeviceManagerService
  });
  gatebluService.whenConfigExists((function(_this) {
    return function() {
      return gatebluService.start();
    };
  })(this));
  return gatebluService;
});

var _;

_ = require('lodash');

angular.module('gateblu-ui').service('LogService', function() {
  var MAX_LOG_LINES, logs;
  logs = [];
  MAX_LOG_LINES = 100;
  return {
    add: (function(_this) {
      return function(log, type) {
        var entry, message;
        message = log;
        try {
          if (!_.isString(log)) {
            message = JSON.stringify(log).toString();
          }
        } catch (undefined) {}
        entry = {
          type: type,
          message: message,
          timestamp: new Date(),
          rawMessage: log
        };
        logs.unshift(entry);
        return logs = _.take(logs, MAX_LOG_LINES);
      };
    })(this),
    all: (function(_this) {
      return function() {
        return logs;
      };
    })(this),
    clear: (function(_this) {
      return function() {
        return logs = [];
      };
    })(this)
  };
});



var UpdateService, _, cmp, fs, path, request,
  bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };

_ = require('lodash');

request = require('request');

cmp = require('semver-compare');

fs = require('fs');

path = require('path');

UpdateService = (function() {
  function UpdateService(dependencies) {
    if (dependencies == null) {
      dependencies = {};
    }
    this.checkUiVersion = bind(this.checkUiVersion, this);
    this.checkServiceVersion = bind(this.checkServiceVersion, this);
    this.checkUI = bind(this.checkUI, this);
    this.checkService = bind(this.checkService, this);
    this.ConfigService = dependencies.ConfigService;
    this.LogService = dependencies.LogService;
    this.http = dependencies.http;
  }

  UpdateService.prototype.checkService = function(version, callback) {
    if (callback == null) {
      callback = function() {};
    }
    return request.get('https://registry.npmjs.org/gateblu-forever', {
      json: true
    }, (function(_this) {
      return function(error, response, body) {
        var updateAvailable;
        if (body == null) {
          return callback(error);
        }
        updateAvailable = cmp(body['dist-tags'].latest, version) > 0;
        return callback(null, updateAvailable, body['dist-tags'].latest);
      };
    })(this));
  };

  UpdateService.prototype.checkUI = function(version, callback) {
    if (callback == null) {
      callback = function() {};
    }
    return request.get('https://registry.npmjs.org/gateblu-ui', {
      json: true
    }, (function(_this) {
      return function(error, response, body) {
        var updateAvailable;
        if (body == null) {
          return callback(error);
        }
        updateAvailable = cmp(body['dist-tags'].latest, version) > 0;
        return callback(null, updateAvailable, body['dist-tags'].latest);
      };
    })(this));
  };

  UpdateService.prototype.checkServiceVersion = function(callback) {
    var ref, thisVersion;
    if (callback == null) {
      callback = function() {};
    }
    thisVersion = (ref = this.ConfigService.servicePackageJson) != null ? ref.version : void 0;
    return this.checkService(thisVersion, (function(_this) {
      return function(error, updateAvailable, newVersion) {
        if (error != null) {
          return callback(error);
        }
        return callback(null, updateAvailable, thisVersion, newVersion);
      };
    })(this));
  };

  UpdateService.prototype.checkUiVersion = function(callback) {
    var ref, thisVersion;
    if (callback == null) {
      callback = function() {};
    }
    thisVersion = (ref = this.ConfigService.uiPackageJson) != null ? ref.version : void 0;
    return this.checkUI(thisVersion, (function(_this) {
      return function(error, updateAvailable, newVersion) {
        if (error != null) {
          return callback(error);
        }
        return callback(null, updateAvailable, thisVersion, newVersion);
      };
    })(this));
  };

  return UpdateService;

})();

angular.module('gateblu-ui').service('UpdateService', function(LogService, ConfigService, $http) {
  return new UpdateService({
    http: $http,
    LogService: LogService,
    ConfigService: ConfigService
  });
});
