/agent.js
var sx = require('simple-xmpp');
var EventEmitter = require('events').EventEmitter;

function Agent() {
    this.roster = {};
    this.presence = {};
    this.events = new EventEmitter();
    ['on', 'addListener', 'once', 'removeListener'].forEach(function(v, i) {
        this[v] = this.events[v].bind(this.events);
    }.bind(this));

    var xmpp = this.xmpp = new sx.SimpleXMPP();

    xmpp.on('error', function(err) {
        console.log(err);
    });

    xmpp.on('chat', function(from, message) {
        // TODO: Pull timestamp from XMPP stanza?
        this.events.emit('message', {
            outbound: false,
            jid: from,
            message: message,
            receivedTimestamp: (new Date()).getTime()
        });
    }.bind(this));

    xmpp.on('buddy', function(jid, status, statusText) {
        switch(status) {
        case xmpp.STATUS.OFFLINE:
            delete this.presence[jid];
            console.log(jid + ' offline');
            this.events.emit('buddy', {
                jid: jid,
                status: status
            });
            break;
        case xmpp.STATUS.ONLINE:
        case xmpp.STATUS.AWAY:
        case xmpp.STATUS.XA:
        case xmpp.STATUS.DND:
            this.presence[jid] = {
                jid: jid,
                status: status,
                statusText: statusText
            };
            this.events.emit('buddy', this.presence[jid]);
            console.log(jid + ' online (' + status + ')');
            break;
        default:
            console.log('unknown status ' + status + ' for ' + jid);
        }
    }.bind(this));
}

Agent.prototype.login = function(username, password, callback) {
    this.xmpp.on('online', function connectCallback() {
        console.log('connected');
        callback();
        this.jid = username;
        this.xmpp.removeListener('online', connectCallback);
    }.bind(this));

    this.xmpp.on('error', function errorCallback(err) {
        callback(err);
        this.xmpp.removeListener('error', errorCallback);
    }.bind(this));

    this.xmpp.connect({
        jid: username,
        password: password
    });
}

Agent.prototype.logout = function() {
    this.xmpp.disconnect();
}

Agent.prototype.getRoster = function(callback) {
    this.xmpp.conn.on('stanza', function rosterReply(stanza) {
        this.xmpp.conn.removeListener('stanza', rosterReply);
        if (stanza.attrs.id == 'roster1') {
            if (stanza.attrs.type == 'error') {
                console.log('error getting roster');
                return callback('error getting roster');
            }
            var items = stanza.getChild('query').getChildren('item');
            this.roster = {};
            for (var i = 0; i < items.length; i++) {
                var attrs = items[i].attrs;
                var groups = items[i].getChildren('group');

                this.roster[attrs.jid] = {
                    jid: attrs.jid,
                    name: attrs.name,
                    subscription: attrs.subscription,
                    groups: groups.map(function(v) {
                        return v.getText();
                    })
                };
            }

            callback(null, this.roster);
        }
    }.bind(this));
    var msg = new this.xmpp.Element('iq', {
        from: this.jid,
        type: 'get',
        id: 'roster1'
    }).c('query', {xmlns: 'jabber:iq:roster'});
    this.xmpp.conn.send(msg);
}

Agent.prototype.sendMessage = function(data) {
    this.xmpp.send(data.jid, data.message);
}

module.exports = Agent;