/*
 * ceSocket v0.0.1
 * Copyright (c) 2011 craft-e.com
 *
 */

;(function($){
	//$.include('http://n4.craft-e.com:8081/socket.io/socket.io.js')

	$.fn.ceSocket = function(url){
		var socket = io.connect(url)
		//var socket = io.connect(ceSocketUrl + '?cePid=' + cePid)
		,	isConnected = false
		,	msgQueue = []
		
		//** socketIsConnected
		,	socketIsConnected = function () {
				isConnected = true
				console.log('connected')
				if (msgQueue.length > 0) {
					console.log('  ' + msgQueue.length + ' messages queued')
					var res, tempQueue = msgQueue
					msgQueue = []

					// send queued messages
					var msg
					for (var i=0; i < tempQueue.length; ++i) {	
						msg = tempQueue[i]
						console.log('  sending: ' + msg.ev + ' : ' + JSON.stringify(msg.o))
						if (msg.isDelivered) {
							// msg.delete
						} else {
							msg.trySending()
						}
					}
				}
			}
		
		
		,	reservedEvents = {'connect':true, 'disconnect': true, 'ping': true}
		,	handlers = {}
		
		,	that = {
				socket: socket

				//** ceSocket.on
			,	on: function(ev, f) {
					
					// if the event isn't one of the reserved events then pass it straight through
					if (reservedEvents[ev] !== true) {
						socket.on(ev, f)
					} else {
					
						// get the array of callbacks for the event and add the callback
						if (!handlers[ev]) {
							handlers[ev] = []
						}
						handlers[ev].push (f)
					}
				}
				
				//** ceSocket.emit
			,	emit: function(ev, o, onSent) {
					ceSocketMessage(ev, o, onSent).trySending()
				}
			}

		
		socket.on('connect' , function() {
			socketIsConnected()
			handleRestrictedEvent('connect')
		})

		socket.on('disconnect', function() {
			console.log('disconnect')
			isConnected = false
			handleRestrictedEvent('disconnect')
		})

		var handleRestrictedEvent = function(ev) {
			if (handlers[ev]) {
				_.each(handlers[ev], function (handler) { handler() })
			}
		}

		socket.on('ping', function(data, callback) {
			callback('ok')
		})
		
		var ceSocketMessage = function (ev, o, onSent) {
			var msg = {
					isDelivered: false
					
					//** ceSocketMessage.trySending
				,	trySending: function() {
						var failed = false
						var timer 
						
						if (isConnected) {
							console.log('  sending: ' + ev + ' : ' + JSON.stringify(o))

							var msgFailed = function () {
								failed = true
								msgQueue.push(msg)
								console.log((' - queuing after trying: ' + JSON.stringify(o)))
							}
							
							// give the message a couple of seconds
							timer = setTimeout(msgFailed, 2 * 1000)
							
							var res = socket.emit(ev, o, function (data) {
								clearTimeout(timer)
								msg.isDelivered = true
								if (onSent) {
									onSent(data)
								}
							})

						} else {
							msgQueue.push(msg)

							var pingFailed = function () {
								failed = true
								console.log((' - queuing after testing: ' + JSON.stringify(o)))
							}

							// give the ping a couple of seconds
							timer = setTimeout(pingFailed, 2 * 1000)

							socket.emit('ping', function(data) {
								if (failed == false) {
									clearTimeout(timer)

									// seems like the socket is alive. reactivate it
									console.log('socket is alive! ' + JSON.stringify(data))
									socketIsConnected()
								}
							})
						}
					}
				}
				
			return msg
		}
		
		return that
	};


})(jQuery);

