FacebookConnector.STATUS_IDLE = 0x0;
FacebookConnector.STATUS_DETECTING = 0x1;
FacebookConnector.STATUS_CONNECTED = 0x2;
FacebookConnector.STATUS_NOT_CONNECTED = 0x4;
FacebookConnector.STATUS_CANCELLED = 0x8;

FacebookConnector.TIMEOUT = 2000;

FacebookConnector.instance = null;

function FacebookConnector() {
	this.apiKey = null;
	this.receiver = null;
	this.swf = null;
	
	this._status = FacebookConnector.STATUS_IDLE;
	this._pendingStatus = null;
	this._timeout = null;
}

FacebookConnector.getInstance = function() {
	if(FacebookConnector.instance == null) {
		FacebookConnector.instance = new FacebookConnector();
	}
	return FacebookConnector.instance;
}

/**
 * Init Facebook Connector and detect existing connection. If an
 * existing connection could be detected, call <code>FacebookConnector.onSessionReady()</code>
 * with the current session. Otherwise execute ExternalInterface call <code>onFBNotConnected()</code>
 * in the SWF.
 * 
 * @param	apiKey		Facebook API key
 * @param	receiver	URL of cross domain receiver file
 * @param	swf		 	SWF DOM object
 */
FacebookConnector.init = function(apiKey, receiver, swf) {
	var instance = FacebookConnector.getInstance();
	if (instance.isInitialised()) {
		return;
	}
	
	instance.apiKey = apiKey;
	instance.receiver = receiver;
	instance.swf = swf;

	instance.setConnectionStatus(FacebookConnector.STATUS_IDLE);

	FB_RequireFeatures( [ "Api" ], function() {
		FB.init(instance.apiKey, instance.receiver, {
			"ifUserConnected" : function() {
				if (FB.Facebook.apiClient.get_session()) {
					instance.setConnectionStatus(FacebookConnector.STATUS_CONNECTED);
				} else {
					instance.setConnectionStatus(FacebookConnector.STATUS_NOT_CONNECTED);
				}
			},
			"ifUserNotConnected" : function() {
				instance.setConnectionStatus(FacebookConnector.STATUS_NOT_CONNECTED);
			}
		});
	});
}

/**
 * Check if connector is initialised
 * @return	<code>true</code> if <code>FacebookConnector.init()</code>
 * 			has successfully been executed
 */
FacebookConnector.prototype.isInitialised = function() {
	return this.apiKey != null && this.swf != null;
}

/**
 * Initiate Facebook connection
 * Once the connection has been established, call <code>FacebookConnector.onSessionReady()</code>.
 * If the user cancels the connecting process, the ExternalInterface call
 * <code>onFBConnectCancelled</code> will be triggered.
 */
FacebookConnector.connect = function() {
	var instance = FacebookConnector.getInstance();
	if (!instance.isInitialised()) {
		return;
	}

	FB.Bootstrap.requireFeatures( [ "Connect" ], function() {
		FB.Connect.requireSession(function(e) {
			instance.setConnectionStatus(FacebookConnector.STATUS_CONNECTED);
		}, function(e) {
			instance.setConnectionStatus(FacebookConnector.STATUS_CANCELLED);
		});
	});
}

/**
 * Close existing Facebook connection. Triggers ExternalInterface method
 * <code>onFBSessionClosed()</code> when logout is complete.
 */
FacebookConnector.disconnect = function() {
	var instance = FacebookConnector.getInstance();
	if (!instance.isInitialised()) {
		return;
	}

	FB.Bootstrap.requireFeatures( [ "Connect" ], function() {
		FB.Connect.logout();
	});
}

FacebookConnector.showFriendsInvitation = function() {
	var instance = FacebookConnector.getInstance();
	if (!instance.isInitialised()) {
		return;
	}
	
	var fb_getInviteFBML = function() {
	    var uid = FB.Facebook.apiClient.get_session().uid;
	    var fbml = "";
	    fbml = 
	    '<fb:fbml>\n' +
	        '<fb:request-form\n'+
	                            //Redirect back to this page
	                            ' action="'+ document.location +'"\n'+
	                            ' method="POST"\n'+
	                            ' invite="true"\n'+
	                            ' type="Red Bull Flight Lab"\n' +
	                            ' content="Join Red Bull Flight Lab'+
	                            ' <fb:req-choice url=\'http://www.redbullflightlab.com/\' label=\'Check out Red Bull Flight Lab\' />"\n'+
	                       '>\n'+
	                       ' <fb:multi-friend-selector\n'+
	                            ' rows="3"\n'+
	                            ' cols="4"\n'+
	                            ' bypass="cancel"\n'+
	                            ' showborder="false"\n'+
	                            ' actiontext="Use this form to invite your friends to connect with Red Bull Flight Lab."/>\n'+
	                ' </fb:request-form>'+
	        ' </fb:fbml>';
	    return fbml;
	};

	FB.Bootstrap.requireFeatures( [ "Connect" ], function() {
		var fbml = fb_getInviteFBML() ;
		var dialog = new FB.UI.FBMLPopupDialog("Invite your friends", fbml) ;
		dialog.setContentWidth(630);
		dialog.setContentHeight(600);
		dialog.show();
	});

}

FacebookConnector.prototype.setConnectionStatus = function(status) {
	if(this._status == status || this._pendingStatus == status) {
		return;
	}
	
	if(this._timeout) {
		window.clearTimeout(this._timeout);
	}

	this._pendingStatus = status;
	
	/*
	 * When setting the status for the first time, apply the status
	 * immediately. Start timeout otherwise.
	 */
	if(this._status == FacebookConnector.STATUS_IDLE) {
		this._applyStatus();
	} else {
		this._timeout = window.setTimeout("FacebookConnector.getInstance()._applyStatus()", FacebookConnector.TIMEOUT);
	}
}

FacebookConnector.prototype._applyStatus = function() {
	if(!this.isInitialised()) {
		return;
	}
	
	this._status = this._pendingStatus;

	switch(this._status) {
	case FacebookConnector.STATUS_NOT_CONNECTED:
		if (this.swf.onFBNotConnected) {
			this.swf.onFBNotConnected();
		}
		break;
		
	case FacebookConnector.STATUS_CONNECTED:
		var session = FB.Facebook.apiClient.get_session();
		if (this.swf.onFBSessionReady) {
			this.swf.onFBSessionReady(session.secret, session.session_key);
		}
		break;
		
	case FacebookConnector.STATUS_CANCELLED:
		if (this.swf.onFBConnectCancelled) {
			this.swf.onFBConnectCancelled();
		}
		break;
	}
 }

/**
 * Show Facebooks permission dialogue for the given permissions. Triggers the
 * ExternalInterface method <code>onFBPermissionsGranted()</code> with the
 * granted permissions once the dialoguge has been closed.
 * 
 * @param	permissions	A comma separated list of Facebook permissions the
 * 			application asks for
 */
FacebookConnector.showGrantExtendedPermissions = function(permissions) {
	var instance = FacebookConnector.getInstance();
	if (!instance.isInitialised()) {
		return;
	}

	FB.Bootstrap.requireFeatures( [ "Connect" ], function() {
		FB.Connect.showPermissionDialog(permissions, function(permissionsGranted) {
			if (instance.swf.onFBPermissionsGranted) {
				instance.swf.onFBPermissionsGranted(permissionsGranted);
			}
		});
	});
}
