var Idle, exec, os, path,
  bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };

exec = require('child_process').exec;

os = require('os');

path = require('path');

Idle = (function() {

  /* Private */
  Idle.prototype.listeners = null;


  /* Public */

  function Idle() {
    this.removeListener = bind(this.removeListener, this);
    this.addListener = bind(this.addListener, this);
    this.listeners = [];
  }

  Idle.prototype.addListener = function(shouldSeconds, callback) {
    var checkIsAway, isAfk, listenerId, timeoutRef;
    isAfk = false;
    listenerId = this.listeners.push(true) - 1;
    timeoutRef = null;
    checkIsAway = (function(_this) {
      return function() {
        if (!_this.listeners[listenerId]) {
          clearTimeout(timeoutRef);
          return;
        }
        return _this.tick(function(isSeconds) {
          var s, whenSeconds;
          whenSeconds = _this.whenToCheck(isSeconds, shouldSeconds);
          s = 1000;
          if (whenSeconds === 0 && !isAfk) {
            callback({
              status: 'away',
              seconds: isSeconds,
              id: listenerId
            });
            isAfk = true;
            return timeoutRef = setTimeout(checkIsAway, s);
          } else if (isAfk && whenSeconds > 0) {
            callback({
              status: 'back',
              seconds: isSeconds,
              id: listenerId
            });
            isAfk = false;
            return timeoutRef = setTimeout(checkIsAway, whenSeconds * s);
          } else if (whenSeconds > 0 && !isAfk) {
            return timeoutRef = setTimeout(checkIsAway, whenSeconds * s);
          } else {
            return timeoutRef = setTimeout(checkIsAway, s);
          }
        });
      };
    })(this);
    checkIsAway();
    return listenerId;
  };

  Idle.prototype.removeListener = function(listenerId) {
    this.listeners[listenerId] = false;
    return true;
  };


  /* Private */

  Idle.prototype.whenToCheck = function(isSeconds, shouldSeconds) {
    var whenSeconds;
    whenSeconds = shouldSeconds - isSeconds;
    if (whenSeconds > 0) {
      return whenSeconds;
    } else {
      return 0;
    }
  };

  Idle.prototype.tick = function(callback) {
    var cmd;
    if (callback == null) {
      callback = function() {};
    }
    if (/^win/.test(process.platform)) {
      cmd = '"' + path.join(__dirname, 'bin', 'idle.exe') + '"';
      return exec(cmd, function(error, stdout, stderr) {
        if (error) {
          callback(0, error);
          return;
        }
        return callback(Math.floor(parseInt(stdout, 10) / 1000), null);
      });
    } else if (/darwin/.test(process.platform)) {
      cmd = '/usr/sbin/ioreg -c IOHIDSystem | /usr/bin/awk \'/HIDIdleTime/ {print int($NF/1000000000); exit}\'';
      return exec(cmd, function(error, stdout, stderr) {
        if (error) {
          callback(0, error);
          return;
        }
        return callback(parseInt(stdout, 10), null);
      });
    } else if (/linux/.test(process.platform)) {
      cmd = 'xprintidle';
      return exec(cmd, function(error, stdout, stderr) {
        if (error) {
          callback(0, error);
          return;
        }
        return callback(Math.round(parseInt(stdout, 10) / 1000), null);
      });
    } else {
      return callback(0);
    }
  };

  return Idle;

})();

module.exports = new Idle();
