/**
* Description
*
* Copyright 2011, Nodes.dk. All Rights Reserved.
*
* @author kasper jensen <kj@nodes.dk>
* @created 07-1-2011 03:04 PM
*/
(function($){
	var methods = {
		/*
		* init,
		* set the FBAuthPath url,
		* and does so dom items tagged with the FacebookRequireLoginLink class becomes login buttons
		* if used on a link, it will redirect to link path when done, or stop the link from redirection if login fails
		*/
		init:function(options){
			options = (options == undefined) ? {}:options;

			if(options.FBAuthPath != undefined) {
				configuration.FBAuthPath = options.FBAuthPath;
			}

			jQuery('.FacebookRequireLoginLink').live('click', function(e){
				var _self = jQuery(this);

				jQuery.Nodes('silentLogin', {
					callback:function(){
						jQuery.Nodes('redirect', _self.attr('href'));
					},
					scope:options['scope']
				});

				e.preventDefault();
				e.stopPropagation();
			});
		},
		/*
		* Creates a url like the cake way, doesnt currently worl that well with non standard URL's
		* needs some more work to work properly however
		*
		* options:
		*	plugin:string		plugin name
		*	controller:string	controller name
		*	action:string		action name
		*/
		url:function(options){
			if(typeof options === 'string') {
				return options;
			}

			//set variables depending on URL
			var plugin = (options.plugin != undefined) ? options.plugin:window.location.toString().split(Nodes.Router.applicationPrefix())[1].split("/")[1];
			var controller = (options.controller != undefined) ? options.controller:window.location.toString().split(Nodes.Router.applicationPrefix())[1].split("/")[2];
			var action = (options.action != undefined) ? options.action:'';

			delete options.plugin;
			delete options.controller;
			delete options.action;

			var args = "";
			for (var action_argument in options) {
				args += "/" + options[action_argument];
			}

			return Nodes.Router.applicationPrefix() + "/" + plugin + "/" + controller + "/" + action + args;
		},
		/*
		* Logs the user in silently so login dialog is only shown if needed, and sends newest session to server
		*
		* For all options also see @authenticateToPHP and @authenticateToFacebook
		*
		* options:
		*	scope:string		(Default: '') 		The Facebook oAuth permissions we need from the user
		*	refreshLogin:bool	(Default: false)	If we should always call authenticateToPHP even if we have a session
		*/
		silentLogin: function (options) {
			var options					    = jQuery.isEmptyObject(options) ? { } : options;
			options['scope'] 			    = options['scope'] || '';
			options['scope']			    = jQuery.trim(options['scope']);
			options['refreshLogin']			= (typeof options['refreshLogin'] == 'undefined' ? false : options['refreshLogin']);

			// oAUTH 2.0 specs
			if(options['scope'].length > 0) {
				FB.getLoginStatus(function(response) {
					options.response = response;
					if (response.authResponse && !options['refreshLogin']) {
						jQuery.Nodes('authenticateToPHP', jQuery.extend({ }, options));
					} else {
						jQuery.Nodes('authenticateToFacebook', jQuery.extend({ }, options));
					}
				});
			} else {
				jQuery.Nodes('authenticateToFacebook', jQuery.extend({ }, options));
			}
		},
		/*
		* Authenticate to CakePHP by calling FacebookUsers::authenticate with FB.getAuthResponse() response data
		*
		* options:
		*	FBAuthPath:string		(Default: /core/facebook_users/authenticate)	Where to post the facebook_session
		*	processAppRequests:bool	(Default: true)									Should app request invites be procssed for the user?
		*	callback:lambda			(Default: null)									Callback to execute when authentication has been done
		*/
		authenticateToPHP: function(options) {
			var options					    = jQuery.extend({ }, options);
			options['FBAuthPath'] 		    = options['FBAuthPath'] || configuration['FBAuthPath'];
			options['processAppRequests']	= (typeof options['processAppRequests'] == 'undefined' ? true : options['processAppRequests']);

			jQuery.post(
				options.FBAuthPath,
				{
					'data': {
						'facebook_session'	: FB.getAuthResponse(),
						'processAppRequests': options['processAppRequests'] ? 1 : 0
					}
				},
				function(FBAuthResponse) {
					if (typeof options.callback == 'function') {
						options.callback.call(this, options.response, FBAuthResponse);
					}
				}
			);
		},
		/*
		* Authenticates to Faceebook (eg. ask for permissions)
		*
		* options:
		*	error_title:string		(Default: i18n specific)	Title of error dialog if user rejects permissions
		*	error_message:string	(Default: i18n specific)	Message body of error dialog if user rejects permissions
		*	css:mixed				(Default: empty string)		Css for the error dialog if user rejects permissions
		*	showDialog:boolean		(Default: true)				Show error dialog if user rejects permissions
		*/
		authenticateToFacebook: function(options) {
			var defaults = {
				'error_title': Nodes.translate('fbPermissionDialog.cancel.title'),
				'error_message': Nodes.translate('fbPermissionDialog.cancel.message'),
				'css': ''
			};

			var options = jQuery.extend({}, defaults, options);
			options['showDialog'] 	= (typeof options['showDialog'] == 'undefined' ? true : options['showDialog']);
			options['css'] 			= options['css'] || { };

			FB.login(function(response) {
				if (response.authResponse){
					jQuery.Nodes('authenticateToPHP', jQuery.extend({ }, options, { 'response': response }));
				} else {
					if(options.errorCallback) {
						options.errorCallback.call(this, response);
					}
					if(options.showDialog) {
						jQuery.Nodes('fbDialog', {
							title: options.error_title,
							message: options.error_message,
							css: options.css
						});
					}
				}
			}, {
				'scope': options['scope']
			});
		},
		/**
		* Process app requests into the backend
		*
		* options:
		*	url:string		The URL to post the facebook request data
		*	data:object		The Facebook App Request data
		*	success:lambda	Callback function for jQuery.ajax "success" callback
		*	error:lambda	Callback function for jQuery.ajax "error" callback
		*	complete:lambda	Callback function for jQuery.ajax "complete" callback
		*/
		processAppRequests: function(options) {
			var defaults = {
				url		: configuration.appRequestPath,
				data	: { },
				success : function(response) { },
				error	: function(response) { },
				complete: function(response) { }
			};
			var settings = jQuery.extend({ }, defaults, options);

			jQuery.ajax({
				'url'		: settings['url'],
				'type'		: 'post',
				'data'		: {
					'data': settings['data']
				},
				'dataType'	: 'json',
				'success'	: settings['success'],
				'complete'	: settings['complete'],
				'error'		: settings['error']
			})
		},
		userGrantedAppPermissions: function(options) {
			if(options['scope'] == "") {
				options['yes'].call();
				return;
			}

			var options = options;
			var required_permissions = options['scope'].split(',');

			FB.api('/me/permissions', function(response) {
				var app_permissions = response['data'][0];
				var success = true;
				jQuery(required_permissions).each(function(k, v) {
					if (typeof app_permissions[v] == "undefined") {
						success = false;
						return false;
					}
				});

				if (success) {
					options['yes'].call();
				} else {
					options['no'].call();
				}
			});
		},
		/*
		* redirect function used for javascript redirects
		* very buggy avoid using it until fixed..
		*
		* @DEPRECATED
		*/
		redirect:function(options){
			//#TODO add in so ajax pages are supported
			//#TODO add in so you can add post params
			//#TODO add require login option, also effectively working as a way of sending a refreshed session to the server
			window.location = jQuery.Nodes('url', options);
		},

		/*
		* fbDialog
		* show a standard dialog
		* options:
		*	css:object					,define css be appended to dialog
		*	title:string				,define dialog title
		*	message:string				,define dialog content
		*	callback:function(options)	,function called after dialog appears, recieves options as parameter
		*	onClose:function(options)	,function called after dialog is closed (on "OK"), recieves options as parameter
		*	persistant:bool=false		,removes the "close" button
		*/
		fbDialog:function(options) {
			var _self =	 this;
			//#TODO add type:"confirm" option, to turn it into a confirm dialog with a callback
			//#TODO auto scroll to the message

			//dialog html template
			var template = jQuery('<div class="popup_tpl" style="display: block; width: 350px; top: 40px; left: 40px;"> ' +
			'	<div class="p_top"> ' +
			'		<div class="p_bg1"></div> ' +
			'		<div class="p_bg2"></div> ' +
			'	</div> ' +
			'	<div class="cn_popup"> ' +
			'		<div class="p_cn_wrapper"> ' +
			'			<div class="p_title">Der opstod en fejl</div> ' +
			'			<div class="p_info_bar"></div> ' +
			'			<div class="p_pad" style="color: rgb(51, 51, 51); overflow-x: auto; overflow-y: auto; ">CONTENT HERE</div> ' +
			'		</div> ' +
			'		<div class="p_nav"> ' +
			'			<div class="p_nav_inner"> ' +
			'				<a href="#" class="p_btn p_cancel">OK</a> ' +
			'			</div> ' +
			'		</div> ' +
			'	</div> ' +
			'	<div class="p_bottom"> ' +
			'		<div class="p_bg1"></div> ' +
			'		<div class="p_bg2"></div> ' +
			'	</div> ' +
			'</div>');

			//set body position if not set already
			//jQuery('body').css('position', ((jQuery('body').css('position') != "relative" && jQuery('body').css('position') != "absolute") ? 'relative':jQuery('body').css('position') ));

			if(options.width != undefined){
				template.css('width', options.width)
			}

			if(options.height != undefined){
				template.find('.p_pad').css('height', options.height)
			}

			if(options.persistant) {
				template.find('.p_cancel').remove();
			}

			template.find('.p_title').html(options.title);
			template.find('.p_pad').html(options.message);

			template.hide();

			jQuery('body').append(template);

			template.css({
				'top':(jQuery('html').height()/2 - template.height()/2),
				'left':(jQuery('html').width()/2 - template.width()/2)
			});

			if(options.css) {
				template.css(options.css);
			}

			template.find('.p_cancel').click(function(e){
				var _self = this;

				jQuery(_self).parents('.popup_tpl').fadeOut('normal', function(){
					jQuery(_self).parents('.popup_tpl').remove();
					if(options.onClose) {
						options.onClose.call(_self, options);
					}
				});
				e.preventDefault();
				e.stopPropagation();
			});
			template.fadeIn('normal', function() {
				if(options.callback) {
					options.callback.call(_self, options);
				}
			});

			return template;
		}
	};

	var configuration = {
		FBAuthPath		: null,
		appRequestPath	: null,
		ajax_page		: null
	}

	jQuery.Nodes = function( method ) {
		if (configuration.FBAuthPath == null) {
			configuration.FBAuthPath = Nodes.Router.applicationPrefix() + '/core/facebook_users/authenticate.json';
		}

		if (configuration.appRequestPath == null) {
			configuration.appRequestPath = Nodes.Router.applicationPrefix() + '/core/facebook_requests/add.json';
		}

		if (methods[method] ) {
			return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
		} else if ( typeof method === 'object' || ! method ) {
			return methods.init.apply( this, arguments );
		} else {
			jQuery.error( 'Method ' +  method + ' does not exist on jQuery.Nodes' );
		}
	};

	})( jQuery );
