//= require <mootools-core-1.3-full-nocompat>
//= require <puremvc-mootools-port>
//= require <uiframework/UIDUtil>
var AsyncProxy = function()
{
	this.Extends = Proxy;
	/**
	 * A hash of pending requests waiting for a response from the server
	 * 
	 * @type Object
	 */
	this.pending = null;

	/**
	 * @private
	 */
	this.initialize = function()
	{
		this.parent(AsyncProxy.NAME,
		{
			userInfo : null
		});
		this.pending = {};

		// Binding
		this.checkCookieResultHandler = this.checkCookieResultHandler.bind(this);
		this.authUserResultHandler = this.authUserResultHandler.bind(this);
		this.logoutResultHandler = this.logoutResultHandler.bind(this);
		this.contentResultHandler = this.contentResultHandler.bind(this);
		this.listingPreviewResultHandler = this.listingPreviewResultHandler.bind(this);
		this.newAccountSetupResultHandler = this.newAccountSetupResultHandler.bind(this);
		this.checkUsernamResultHandler = this.checkUsernamResultHandler.bind(this);
	};

	// ------------------------------------------------------
	// Async request initializers
	this.checkCookie = function()
	{
		var cookieCheck = this.getRequestJSON("checkCookie", this.checkCookieResultHandler);
		cookieCheck.post(
		{
			command : "checkCookie",
			uid : cookieCheck.uid
		});
	};

	this.authenticateUser = function(data)
	{
		var authUser = this.getRequestJSON("authUser", this.authUserResultHandler);
		data.command = "authUser";
		data.uid = authUser.uid;
		authUser.post(data);
	};

	this.logoutUser = function()
	{
		var logout = this.getRequestJSON("logout", this.logoutResultHandler);
		logout.post(
		{
			command : "logout",
			uid : logout.uid
		});
	};

	this.getPageContent = function(hashObj)
	{
		// Cancel the old request if it is still pending
		if (this.pending.getPageContent)
		{
			var rqObj = this.pending.getPageContent;
			rqObj.cancel();
			delete this.pending.getPageContent;
		}
		var contentRequest = this.getRequestJSON("getPageContent", this.contentResultHandler);
		hashObj.command = 'getPageContent';
		hashObj.uid = contentRequest.uid;
		this.pending['getPageContent'] = contentRequest;
		contentRequest.post(hashObj);
	};

	this.getListingPreview = function(listingId)
	{
		// Cancel the old request if it is still pending
		if (this.pending.getListingPreview)
		{
			var rqObj = this.pending.getListingPreview;
			rqObj.cancel();
			delete this.pending.getListingPreview;
		}
		var data =
		{
			listingId : listingId
		};
		var contentRequest = this.getRequestJSON("getListingPreview", this.listingPreviewResultHandler);
		data.command = 'getListingPreview';
		data.uid = contentRequest.uid;
		this.pending['getListingPreview'] = contentRequest;
		contentRequest.post(data);
	};
	
	this.newAccountSetup = function(data)
	{
		var newAccountRequest = this.getRequestJSON("newAccount", this.newAccountSetupResultHandler);
		data.command = "newAccount";
		newAccountRequest.post(data);
	};
	
	this.checkUsername = function(data)
	{
		var checkUsernameRequest = this.getRequestJSON("checkUsername", this.checkUsernamResultHandler);
		data.command = "checkUsername";
		checkUsernameRequest.post(data);
	};

	// -------------------------------------------------------
	// Event Handlers
	
	this.checkCookieResultHandler = function(obj)
	{
		this.data.userInfo = obj;
		this.sendNotification(AsyncProxy.COOKIE_CHECK_RESULT, obj);
	};

	this.authUserResultHandler = function(obj)
	{
		this.data.userInfo = obj;
		this.sendNotification(AsyncProxy.AUTH_USER_RESULT, obj);
	};

	this.logoutResultHandler = function(obj)
	{
		if (obj.success == true)
			this.data.userInfo = null;
		this.sendNotification(AsyncProxy.LOGOUT_RESULT, obj);
	};

	this.contentResultHandler = function(obj)
	{
		// Verify the uid's match before
		// notifying the system
		var uid = obj.uid;
		var rq = this.pending['getPageContent'];
		if (rq && rq.uid == uid)
		{
			delete this.pending['getPageContent'];
			this.sendNotification(AsyncProxy.CONTENT_RECEIVED, obj);
		}
	};

	this.listingPreviewResultHandler = function(obj)
	{
		// Verify the uid's match before
		// notifying the system
		var uid = obj.uid;
		var rq = this.pending['getListingPreview'];
		if (rq && rq.uid == uid)
		{
			delete this.pending['getListingPreview'];
			this.sendNotification(AsyncProxy.LISTING_PREVIEW_RECIEVED, obj);
		}
	};
	
	this.newAccountSetupResultHandler = function(obj)
	{
		this.sendNotification(AsyncProxy.NEW_ACCOUNT_RESULT, obj);
	};
	
	this.checkUsernamResultHandler = function(obj)
	{
		this.sendNotification(AsyncProxy.USERNAME_CHECK_RESULT, obj);
	};

	// --------------------------------------------------
	// Helper functions

	/**
	 * Dispatches a notification when a request is sent
	 */
	this.requestSent = function()
	{
		this.owner.sendNotification(AsyncProxy.ASYNC_SENT, this.type);
	};

	/**
	 * Creates a Request.JSON object with appended properties and event
	 * listeners required to integrate into the notification system.
	 * 
	 * @param type
	 *            String identifying the request type
	 * @param onSuccess
	 *            Function called when the request is successful.
	 * @return Request A new request object instance.
	 */
	this.getRequestJSON = function(type, onSuccess)
	{
		var request = new Request.JSON(
		{
			url : AsyncProxy.GATEWAY,
			onSuccess : onSuccess,
			onRequest : this.requestSent
		});
		// Dynamically added properties
		request.type = type;
		request.uid = UIDUtil.createUID();
		request.owner = this;
		return request;
	};
};
AsyncProxy = new Class(new AsyncProxy());
// ---------------------------------------------------------------
// Notification constants
AsyncProxy.NAME = "AsyncProxy";
AsyncProxy.GATEWAY = "index.php";
AsyncProxy.ASYNC_SENT = "asyncSent";
AsyncProxy.COOKIE_CHECK_RESULT = "cookieCheckResult";
AsyncProxy.AUTH_USER_RESULT = "authUserResult";
AsyncProxy.LOGOUT_RESULT = "logoutResult";
AsyncProxy.CONTENT_RECEIVED = "contentRecieved";
AsyncProxy.LISTING_PREVIEW_RECIEVED = "listingPreviewRecieved";
AsyncProxy.NEW_ACCOUNT_RESULT = "newAccountResult";
AsyncProxy.USERNAME_CHECK_RESULT = "usernameCheckResult";
