(function($) {
	
Pie.Users = (function() {
	var me = {
		facebookApps: {} // this info gets added by the server, on the page
	};
	var priv = {};

	Pie.text.users = {

		login: {
			title: 'Welcome',
			explanation: "You will create a new account or log in.",
			goButton: "Go",
			loginButton: "Come Inside",
			registerButton: "Get Started",
			resendButton: "Re-send Activation Message",
			noPassphrase: "Before you can log in, you must set a pass phrase by clicking the link in the email we sent.",
			emailExists: "Did you try to register with this email before? If so, check your inbox to activate your account. <a href='#resend'>Click to re-send the message</a>.",
			mobileExists: "Did you try to register with this mobile number before? If so, check your SMS to activate your account. <a href='#resend'>Click to re-send the message</a>.",
			usingOther: "or you can ",
			facebookSrc: null
		},
		
		setIdentifier: {
			sendMessage: "Send Activation Message"
		}

	};
	
	me.info = {};

	/**
	 * Processes the response, and may alleviate some errors
	 * @param Function success
	 *  Calls this callback if all errors could be alleviated
	 * @param Function errors
	 *  Calls this callback if some errors could not be alleviated
	 */
	me.errors = function(response, onErrors, onSuccess)
	{
		var i = 0;
		var alleviated = true;
		if (response.errors) {
			for (i=0; i<response.errors.length; ++i) {
				var error = response.errors[i];
				if (error.classname === 'Users_Exception_NotLoggedIn') {
					// Ask the user to log in again
					me.login({
						onSuccess: onSuccess
					});
				} else {
					alleviated = false;
					Pie.handle(onErrors, window, [response]);
				}
			}
		}
		if (alleviated) {
			Pie.handle(onSuccess, window, [response]);
		}
	}


	me.initFacebook = function(callback, options) {
		options = options || {};
		if (!$('#fb-root').length) {
			$('body').append($('<div id="fb-root" />'));
		}
		Pie.addScript('http://connect.facebook.net/en_US/all.js', function () {
			FB.init(Pie.extend({
				appId: Pie.Users.facebookApps[Pie.app].appId,
				status: true,
				cookie: true,
				xfbml: true,
				oauth: true
			}));
			if (callback) {
				callback();
			}
		});
	};
	
	me.login = function(options) {
		var o = {
			'onCancel': null,
			'onSuccess': null, // gets passed session
			"accountStatusUrl": null,
			'onRequireComplete': false,
			'tryQuietly': false,
			'using': 'native', // can also be 'facebook'
			'perms': 'email,publish_stream', // the permissions to ask for on facebook
			"linkName": null
		};
		if (typeof options === 'function') {
			o.onSuccess = options;
			if (arguments.length > 1) {
				o.onRequireComplete = arguments[1];
			}
		} else {
			$.extend(o, options);
		}
		
		var dest;
		function onConnect(response) {
			if (!o.accountStatusUrl) {
				onComplete(response);
				return;
			}
			Pie.jsonRequest(o.accountStatusUrl, 'accountStatus', function(response2) {
				// DEBUGGING: For debugging purposes
				if (!response2.slots) {
					if (response2.errors && response2.errors[0].message) {
						alert(response2.errors[0].message);
					}
					return;
				}

				if (!o.onRequireComplete || response2.slots.accountStatus === 'complete') {
					onComplete(response);
				} else if (response2.slots.accountStatus === 'refresh') {
					// we are logged in, refresh the page
					document.location.reload(true);
					return;
				} else {
					// take the user to the profile page
					// which will show the account process,
					// until completed -- and then the profile!
					if (typeof(o.onRequireComplete) !== 'function'
					 && typeof(o.onRequireComplete) !== 'string') {
						alert('Need a url in the onRequireComplete option');
						return;
					}
					Pie.handle(o.onRequireComplete, this, [response, response2]);
				}
			});
		};
		
		function onCancel(response) {
			Pie.handle(o.onCancel, this, [response]);
		}
		
		function onComplete(response) {
			if (!o.onSuccess 
			&& typeof(o.onSuccess) !== 'function'
			&& typeof(o.onSuccess) !== 'string') {
				alert('Need a url in the onSuccess option');
				return;
			}
			Pie.handle(o.onSuccess, this, [response]);
		}

		if (typeof o.using === 'string') {
			o.using = o.using.split(',');
		}

		if (o.tryQuietly) {
			if (o.using[0] === 'facebook') {
				me.initFacebook(function () {
					FB.getLoginStatus(function(response) {
						if (response.authResponse) {
							onConnect(response);
						} else {
							onCancel(response);
						}
					});
				});
			}
			return false;
		}

		if (o.using[0] === 'native') {
			var usingServices = [];
			if (o.using.length > 1) {
				if (o.using[1] === 'facebook') {
					usingServices = ['facebook'];
				}
			}
			login_setupOverlay(usingServices, o.perms);
			function showOverlay() {
				if (o.linkName) {
					priv.linkName = o.linkName;
					var url = Pie.url('/action.php/users/link') + '?name=' 	
						+ encodeURIComponent(o.linkName);
					Pie.jsonRequest(url, 'data', function (response) {
						var form = $('#users_login_step1_form').eq(0);
						$('input', form).val(response.slots.data.login);
						form.submit();
					});
				} else {
					$('#users_login_step1').show();
					$('#users_login_usingServices').show();
					$('#users_login_step1_form *').removeAttr('disabled');
				}
				$('#users_login_overlay').data('overlay').load();
			}
			priv.login_onConnect = onConnect;
			priv.login_onCancel = onCancel;
			priv.linkName = null;
			if ($.fn.overlay) {
				showOverlay(usingServices);
			} else {
				Pie.addScript('http://cdn.jquerytools.org/1.2.3/full/jquery.tools.min.js', showOverlay);
			}
		} else if (o.using[0] === 'facebook') {
			me.initFacebook(function () {
				var opts = o.perms ? {perms: o.perms} : undefined;
				FB.login(function(response) {
					if (response.authResponse && (response.perms || !o.perms)) {
						onConnect(response);
					} else {
						onCancel(response);
					}
				}, o);
			});
		}
		
		// you can now require login and do FQL queries:
		return false;
	};
	
	me.logout = function(options) {
		var urls = Pie.urls || {};
		var o = {
			'url': urls[Pie.app+'/logout'],
			'onSuccess': urls[Pie.app+'/welcome'] || Pie.url(''),
			'using': 'native' 
		};
		if (typeof options === 'function') {
			o.onSuccess = options;
		} else {
			$.extend(o, options);
		}
		if (!o.url) {
			return false;
		}	
                if (typeof o.using === 'string') {
                        o.using = o.using.split(',');
                }
	
		var callback = function(response) {
			if (response.slots && response.slots.script) {
				// This script is coming from our server - it's safe.
				try {
					eval(response.slots.script);
				} catch (e) {
					alert(e);
				}
			}
			if (o.using[0] === 'facebook' || o.using[1] === 'facebook') {
				me.initFacebook(function () {
					if (FB.getAuthResponse()){
						FB.logout(function(response) {
							Pie.handle(o.onSuccess);
						});
					} else {
						Pie.handle(o.onSuccess);
					}
				});
			} else {
				Pie.handle(o.onSuccess);
			}
		}
		var url = o.url + (o.url.indexOf('?') < 0 ? '?' : '') + '&logout=1';
		Pie.jsonRequest(url, 'script', callback, {"method": "post"});
		return true;
	};
	
	
	me.setIdentifier = function(options) {
		var defaults = {
			'onCancel': null,
			'onSuccess': null // gets passed session
		};
		var o = $.extend(defaults, options);
		
		function onSuccess(response) {
			Pie.handle(o.onSuccess, this, [response]);	
		}
		
		function onCancel(response) {
			Pie.handle(o.onCancel, this, [response]);
		}
		
		priv.setIdentifier_onSuccess = onSuccess;
		priv.setIdentifier_onCancel = onCancel;
		
		setIdentifier_setupOverlay();
		$('#users_setIdentifier_overlay').data('overlay').load();
	};
	
	/**
	 * Private functions
	 */
	function login_callback(response) {
		var identifier_input = $('#users_login_identifier');
		var form = $('#users_login_step1_form');
		identifier_input.css('background-image', 'none');

		if (response.errors) {
			// There were errors
			form.data("validator").invalidate(Pie.ajaxErrors(response.errors, ['identifier']));
			identifier_input.focus();
			return;
		}

		// Remove any errors we may have displayed
		form.data('validator').reset();
		
		var json = response.slots.data;
		var step2_form;
		if (json.exists) {
			if (form.data('used') === 'facebook') {
				// auto-login by authenticating with facebook
				$.post(
					Pie.ajaxExtend(Pie.url("action.php/users/authenticate"), 'data'),
					'identifier='+encodeURIComponent(identifier_input.val()), 
					function (response) {
						if (response.errors) {
							alert(errors[0].message);
							return;
						}
						if (response.slots.data) {
							var msg = response.slots.data.user && response.slots.data.user.fields.username
							 	? 'Welcome, '+response.slots.data.user.fields.username+'!'
								: 'Success!';
							$('button', step2_form).html(msg).attr('disabled', 'disabled');

							if (priv.login_onConnect) {
								if (login_setupOverlay.overlay) {
									login_setupOverlay.overlay.data('overlay').close();
								}
								priv.login_onConnect(response.slots.data.user);
							}
						}
					},
					'json'
				);
			}
			if (json.passphrase_set) {
				step2_form = setupLoginForm();
			} else {
				step2_form = setupResendForm();
			}
		} else {
			step2_form = setupRegisterForm(json.emailExists, json.mobileExists);
		}

		function onFormSubmit(event) {
			var $this = $(this);
			if (!$this.is(':visible')) {
				event.preventDefault(); return;
			}
			var first_input = $('input:not([type=hidden])', $this).add('button', $this).eq(0);
			$('input', $this).css({
				'background-image': 'url(' + Pie.url('plugins/pie/img/throbbers/bars.gif') + ')',
				'background-repeat': 'no-repeat'
			});
			var url = $this.attr('action')+'?'+$this.serialize();
			Pie.jsonRequest(url, 'data', function (response) {
				$('input', $this).css('background-image', 'none');
				if (response.errors) {
					// there were errors
					$this.data("validator").invalidate(Pie.ajaxErrors(response.errors, [first_input.attr('name')]));
					first_input.focus();
					return;
				}
				// success!
				if ($this.data('form-type') === 'resend') {
					$('button', $this).html('Sent').attr('disabled', 'disabled');
					login_setupOverlay.overlay.data('overlay').close();
					return;
				}
				var msg = response.slots.data.user && response.slots.data.user.fields.username
				 	? 'Welcome, '+response.slots.data.user.fields.username+'!'
					: 'Success!';
				$('button', $this).html(msg).attr('disabled', 'disabled');

				if (priv.login_onConnect) {
					if (login_setupOverlay.overlay) {
						login_setupOverlay.overlay.data('overlay').close();
					}
					priv.login_onConnect(response.slots.data.user);
				}
			}, {"method": "post"});
			event.preventDefault();
		}

		function setupLoginForm() {
			var passphrase_input = $('<input type="password" name="passphrase" id="users_form_passphrase" class="password" />');
			var login_form = $('<form method="post" />')
			.attr('action', Pie.url("action.php/users/login"))
			.data('form-type', 'login')
			.append($('<label for="users_login_passphrase">Enter your pass phrase:</label><br>'))
			.append(passphrase_input)
			.append($('<input type="hidden" name="identifier" autocomplete="on" />').val(identifier_input.val()))
			.append($('<div class="pie_buttons"></div>').append(
				$('<button type="submit" class="users_login_start pie_main_button" />')
				.html(Pie.text.users.login.loginButton)
			));
			return login_form;
		}
		
		function setupResendForm() {
			var identifier_form = $('<form method="post" />')
			.attr('action', Pie.url("action.php/users/resend"))
			.data('form-type', 'resend')
			.append($('<p id="users_login_noPassphrase"></p>').html(Pie.text.users.login.noPassphrase))
			.append($('<div class="pie_buttons"></div>').append(
				$('<button type="submit" class="users_login_start pie_main_button" />')
				.html(Pie.text.users.login.resendButton)
				.attr('name', 'resend')
			)).append($('<input type="hidden" name="identifier" />').val(identifier_input.val()));
			return identifier_form;
		}

		function setupRegisterForm(emailExists, mobileExists) {
			var src = json.entry[0].photos && json.entry[0].photos.length
				? json.entry[0].photos[0].value
				: json.entry[0].thumbnailUrl;
			var username = json.entry[0].preferredUsername || json.entry[0].displayName;
			if (Pie.Users.info.username){
				username = Pie.Users.info.username;
			}
			if (Pie.Users.info.pic_square) {
				src = Pie.Users.info.pic_square;
			}
			var img = $('<img />').attr('src', src).attr('title', 'You can change this picture later');
			if (img.tooltip) {
				img.tooltip();
			}
			var table = $('<table />').append(
				$('<tr />').append(
					$('<td style="width: 80px; padding: 5px;" />').append(img)
				).append(
					$('<td style="padding: 5px;" />').append(
						'<label for="users_login_username">Choose a username:</label><br>'
					).append(
						$('<input id="users_login_username" name="username" class="text" placeholder="username">')
						.val(username)
					)
				)
			);
			var register_form = $('<form method="post" />')
			.attr('action', Pie.url("action.php/users/register"))
			.data('form-type', 'register')
			.append($('<div class="users_login_appear" />').append(table))
			.append($('<input type="hidden" name="identifier" />').val(identifier_input.val()))
			.append($('<input type="hidden" name="icon" />').val(src))
			.append($('<div class="users_login_get_started">&nbsp;</div>').append(
				$('<button type="submit" class="users_login_start pie_main_button" />')
				.html(Pie.text.users.login.registerButton)
			));
			if (emailExists || mobileExists) {
				var p = $('<p id="users_login_identifierExists" />')
					.html(
						emailExists 
						? Pie.text.users.login.emailExists
						: Pie.text.users.login.mobileExists
					);
				$('a', p).click(function() {
					$.post(
						Pie.ajaxExtend(Pie.url("action.php/users/resend"), 'data'),
						'identifier='+encodeURIComponent(identifier_input.val()), 
						function () {
							login_setupOverlay.overlay.data('overlay').close();
						}
					);
					return false;
				});
				register_form.append(p);
			}
			return register_form;
		}

		$('#users_login_usingServices').hide();
		if (form.data('used')) {
			$('*', form).attr('disabled', 'disabled');
		}
		$('#users_login_step2').html(step2_form).slideDown('fast');
		$('#users_login_step1').animate({"opacity": 0.5}, 'fast');
		$('#users_login_step1 button').attr('disabled', 'disabled');
		if (step2_form.data('form-type') === 'resend') {
			$('.pie_main_button', step2_form).focus();
		} else {
			$('input', step2_form).eq(0).focus().select();
		}
		step2_form.validator({
			onFail: function(a, b) {

			}
		}).submit(onFormSubmit);
		if (priv.linkName) {
			$('#users_login_step1').hide();
		}

	}
	
	function login_setupOverlay(usingServices, perms) {
		if (login_setupOverlay.overlay) {
			return;
		}
		if (!usingServices) {
			usingServices = [];
		}
		var step1_form = $('<form id="users_login_step1_form" />');
		var step1_div = $('<div id="users_login_step1" class="pie_big_prompt" />').html(step1_form);
		var step2_div = $('<div id="users_login_step2" class="pie_big_prompt" />');
		step1_form.html(
			'<label for="users_login_identifier">Enter your email address:</label><br>' +
			'<input id="users_login_identifier" type="text" name="identifier" class="text" placeholder="email">&nbsp;'
		).append(
			$('<button type="submit" class="users_login_go pie_main_button" />')
			.html(Pie.text.users.login.goButton)
		).append(
			$('<div id="users_login_explanation" />').html(Pie.text.users.login.explanation)
		).submit(function(event) {
			if (!$(this).is(':visible')) {
				event.preventDefault();
				return;
			}
			$('button', $(this)).focus();
			$('#users_login_identifier').css({
				'background-image': 'url(' + Pie.url('plugins/pie/img/throbbers/bars.gif') + ')',
				'background-repeat': 'no-repeat'
			});
			var url = Pie.url('/action.php/users/user') + '?' + $(this).serialize();
			Pie.jsonRequest(url, 'data', login_callback);
			event.preventDefault();
			return;
		}).bind('keyup keydown change click', function() {
			if (!step1_form.data('used')) {
				if ($('#users_login_step1').next().is(':visible')) {
					$('#users_login_step1').animate({"opacity": 1}, 'fast');
					$('#users_login_step1 button').removeAttr('disabled');
				}
				$('#users_login_step1').nextAll().slideUp('fast').each(function() {
					var v = $('form', $(this)).data('validator');
					if (v) {
						v.reset();
					}
				});
			}
		});
		step1_form.validator();
		var step1_usingServices_div = $('<div id="users_login_usingServices" />');
		for (var i = 0; i < usingServices.length; ++i) {
			switch (usingServices[i]) {
				case 'facebook':
					var facebookLogin = $('<a href="#login_facebook" />').append(
						$('<img alt="login with facebook" />')
						.attr('src', Pie.text.users.login.facebookSrc || Pie.url('plugins/users/img/facebook-login.png'))
					).click(function () {
						me.initFacebook(function () {
							FB.login(function(response) {
								if (!response.authResponse) {
									// The user is still staring at our native login dialog
									return;
								}
								step1_form.data('used', 'facebook');
								FB.api({
									method: 'fql.query',
									query: "SELECT username, email, pic_small, pic_big, pic_square, pic FROM user WHERE uid="+response.authResponse.userID
								},
						        function(rows) {
									Pie.Users.info.username = rows[0].username;
									Pie.Users.info.pic_square = rows[0].pic_square;
									$('#users_login_identifier').val(rows[0].email).closest('form').submit();
						        });
							}, perms ? {perms: perms} : undefined);
						});
						return false;
					});
					step1_usingServices_div.append(Pie.text.users.login.usingOther).append(facebookLogin);
					// Load the facebook script now, so clicking on the facebook button
					// can trigger a popup directly, otherwise popup blockers may complain:
					Pie.addScript('http://connect.facebook.net/en_US/all.js');
					break;
			}
		}
		if (usingServices.length > 0) {
			step1_div.append(step1_usingServices_div);
		}
		var overlay = $('<div class="pie_overlay users_login_overlay" id="users_login_overlay" />');
		overlay.append(
			$('<h2 class="users_dialog_title pie_dialog_title" />').html(Pie.text.users.login.title)
		).append(step1_div)
		.append (step2_div)
		.appendTo('body');
		overlay.overlay({
			// some mask tweaks suitable for modal dialogs
			onBeforeLoad: function() {
				$('#users_login_step1').css('opacity', 1).nextAll().hide();	
				$('input', overlay).val('');
			},
			onLoad: function() {
				$('input', overlay).eq(0).val('').focus();
			},
			onClose: function() {
				$('#users_login_step1 button').removeAttr('disabled');
				$('form', overlay).each(function() {
					var v = $(this).data('validator');
					if (v) {
						v.reset();
					}
				});
				$('#users_login_step1').nextAll().hide();
				if (priv.login_onCancel) {
					priv.login_onCancel();
				}
			}
		});
		/*
		.mouseenter(function() {
			prev_opacity = $(this).css('opacity');
			$(this).animate({'opacity': 1}, 'fast');
		}).mouseleave(function() {
			$(this).animate({'opacity': prev_opacity}, 'fast');
		});
		*/
		login_setupOverlay.overlay = overlay;
	}
	
	function setIdentifier_callback(response) {
		var identifier_input = $('#users_setIdentifier_identifier');
		var form = $('#users_setIdentifier_step1_form');
		identifier_input.css('background-image', 'none');

		if (response.errors) {
			// There were errors
			form.data("validator").invalidate(Pie.ajaxErrors(response.errors, 'identifier'));
			identifier_input.focus();
			return;
		}

		// Remove any errors we may have displayed
		form.data('validator').reset();

		setIdentifier_setupOverlay.overlay.data('overlay').close();
	}
	
	function setIdentifier_setupOverlay() {
		if (setIdentifier_setupOverlay.overlay) {
			return;
		}
		var step1_form = $('<form id="users_setIdentifier_step1_form" />');
		var step1_div = $('<div id="users_setIdentifier_step1" class="pie_big_prompt" />').html(step1_form);
		step1_form.html(
			'<label for="users_setIdentifier_identifier">Enter your email address:</label><br>' +
			'<input id="users_setIdentifier_identifier" type="text" name="identifier" class="text" placeholder="email">'
		).append(
			$('<div class="pie_buttons"/>').html(
				$('<button type="submit" class="users_setIdentifier_go pie_main_button" />').html(
					Pie.text.users.setIdentifier.sendMessage
				)
			)
		).submit(function(event) {
			$('#users_setIdentifier_identifier').css({
				'background-image': 'url(' + Pie.url('plugins/pie/img/throbbers/bars.gif') + ')',
				'background-repeat': 'no-repeat'
			});
			var url = Pie.url('action.php/users/contact') + '?' + $(this).serialize();
 			Pie.jsonRequest(url, 'data', setIdentifier_callback, {"method": "post"});
			event.preventDefault();
			return;
		});
		step1_form.validator();
		var overlay = $('<div class="pie_overlay users_setIdentifier_overlay" id="users_setIdentifier_overlay" />');
		overlay.overlay({
			// some mask tweaks suitable for modal dialogs
			onBeforeLoad: function() {
				$('input', overlay).val('');
			},
			onLoad: function() {
				$('input', overlay).eq(0).val('').focus();
			},
			onClose: function() {
				$('form', overlay).each(function() {
					var v = $(this).data('validator');
					if (v) {
						v.reset();
					}
				});
				if (priv.setIdentifier_onCancel) {
					priv.setIdentifier_onCancel();
				}
			}
		});
		overlay.append('<h2 class="users_dialog_title pie_dialog_title">My Account</h2>')
			.append(step1_div)
			.appendTo('body');
			
		setIdentifier_setupOverlay.overlay = overlay;
	}
	
	return me;

})();




/*
 * users/contact tool
 */

Pie.constructors['users_contact_tool'] = function(prefix) {
	
	// constructor
	var me = this;

	// validate signup form on keyup and submit
	var validator = me.attachValidation();
}

/*
 * users/avatar tool
 */

Pie.constructors['users_avatar_tool'] = function(prefix) {

	// constructor & private declarations
	var me = this;

	
};


})(jQuery);

