/* jshint eqnull:true */
function AdminNotifications(limit) {
	'use strict';
	var endpoint = '/api/v1/notifications/' + (typeof limit === 'number' ? limit : 50),
		proto = location.protocol.indexOf('https') === 0 ? 'wss://' : 'ws://',
		url = proto + location.host + endpoint,
		an = this;

	function Listener(url, cb, autoconnect) {
		this.url = url;
		this.cb = cb;
		this.ws = null;

		var self = this;
		this.pinger = setInterval(function() {
			if (this.ws != null) {
				this.ws.send('--ping--');
			}
		}, 1000 * 45);
	}

	Listener.prototype = {
		connect: function connect(autoreconnect) {
			var self = this;
			this.ws = new WebSocket(this.url)
			if (autoreconnect) {
				var reconnect = function() {
					if (self.ws === null) return;
					self.connect(autoreconnect);
				};
				this.ws.onclose = function() {
					setTimeout(reconnect, 1500);
				};
			}
			var cb = this.cb;
			if (!cb) return
			this.ws.onmessage = function(evt) {
				return cb(JSON.parse(evt.data));
			};
		},
		close: function close() {
			clearInterval(this.pinger);
			if (this.ws == null) return;
			this.ws.onclose = null;
			this.ws.close();
			this.ws = null;
		}
	};

	if (window["WebSocket"]) {
		this._ws = new Listener(url, this._handler.bind(this));
		this._ws.connect(true);
	} else {
		console.error("Your browser does not support WebSockets.")
	}
	this._listeners = {};
	this._backlog = [];
	this.limit = 50;
}

AdminNotifications.prototype = {
	on: function On(evt, cb) { // return false from a handler to stop going down the chain
		if (typeof evt !== 'string') return console.error('evt must be a string');
		if (typeof cb !== 'function') return console.error('cb must be a function');
		if (!Array.isArray(this._listeners[evt])) this._listeners[evt] = [];
		this._listeners[evt].push(cb);
		if(this._backlog.length && evt === '*') {
			this._backlog.sort(function(a, b) {
				if(a.ts === b.ts) return 0;
				return a.ts < b.ts ? -1 : 1;
			});
			this._backlog.forEach(cb);
			this._backlog = [];
		}
	},

	fireEvent: function FireEvent(evt, data) {
		if (Array.isArray(this._listeners['*'])) {
			for (var i = 0, ls = this._listeners['*']; i < ls.length; i++) {
				if (ls[i](data) === false) return;
			}
		}
		if (evt === '*' || !Array.isArray(this._listeners[evt])) return;
		for (var i = 0, ls = this._listeners[evt]; i < ls.length; i++) {
			if (ls[i](data) === false) return;
		}
	},

	_handler: function Handler(data) {
		if(data == null || typeof data !== 'object' || typeof data.type !== 'string') {
			return console.error('unexpected data', data);
		}
		if(!Object.keys(this._listeners).length) {
			this._backlog.push(data);
			return;
		}
		this.fireEvent(data.type, data);
	},

	close: function close() {
		this._ws.close();
	}
};