var FS = require('fs');
var EventEmitter = require('events').EventEmitter;

// http://www.mjmwired.net/kernel/Documentation/input/joystick-api.txt
function parse(buffer) {
  var event = {
    time: buffer.readUInt32LE(0),
    number: buffer[7],
    value: buffer.readInt16LE(4)
  }
  if (buffer[6] & 0x80) event.init = true;
  if (buffer[6] & 0x01) event.type = "button";
  if (buffer[6] & 0x02) event.type = "axis";
  return event;
}

// Expose as a nice JavaScript API
function Joystick(id) {
  this.onOpen = this.onOpen.bind(this);
  this.onRead = this.onRead.bind(this);
  this.buffer = new Buffer(8);
  FS.open("/dev/input/js" + id, "r", this.onOpen);
}
Joystick.prototype = Object.create(EventEmitter.prototype, {
  constructor: {value: Joystick}
});

Joystick.prototype.onOpen = function (err, fd) {
  if (err) return this.emit("error", err);
  this.fd = fd;
  this.startRead();
};

Joystick.prototype.startRead = function () {
  FS.read(this.fd, this.buffer, 0, 8, null, this.onRead);
};

Joystick.prototype.onRead = function (err, bytesRead) {
  if (err) return this.emit("error", err);
  var event = parse(this.buffer);
  this.emit(event.type, event);
  if (this.fd) this.startRead();
};

Joystick.prototype.close = function (callback) {
  FS.close(this.fd, callback);
  this.fd = undefined;
};

////////////////////////////////////////////////////////////////////////////////

// Sample usage
var js = new Joystick(1);
js.on('button', console.log);
js.on('axis', console.log);

// Close after 5 seconds
setTimeout(function () {
  js.close();
}, 5000);