/**
*   This file is part of PICT - The Platform Independent Community Platform.
*   Development of PICT was possible thanks to funding from the JISC (http://www.jisc.ac.uk/)
*   Author: Rory McNicholl (http://www.ulcc.ac.uk/)
*   
*	PICT is free software: you can redistribute it and/or modify
*	it under the terms of the GNU General Public License as published by
*	the Free Software Foundation, either version 3 of the License, or
*	(at your option) any later version.
*
*	PICT is distributed in the hope that it will be useful,
*	but WITHOUT ANY WARRANTY; without even the implied warranty of
*	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*	GNU General Public License for more details.
*
*	You should have received a copy of the GNU General Public License
*	along with Dope OpenID. If not, see <http://www.gnu.org/licenses/>.
**/

/**************** The directory where PICT is installed ***************/
var install_dir = '/pc';
/**********************************************************************/

function pict_load_plugins(){
	// LOAD PLUGINS 
	// Core plugins
	eval(jQuery.ajax({url:install_dir+"/js/jquery/jquery.cookies.2.1.0.min.js", async:false}).responseText);
	eval(jQuery.ajax({url:install_dir+"/js/jquery/json2.js", async:false}).responseText);
	eval(jQuery.ajax({url:install_dir+"/js/jquery/openid-jquery.js", async:false}).responseText);
	eval(jQuery.ajax({url:install_dir+"/js/jquery/jquery.md5.js", async:false}).responseText);
	eval(jQuery.ajax({url:install_dir+"/js/jquery/jquery.validate.min.js",async:false}).responseText);
	eval(jQuery.ajax({url:install_dir+"/js/jquery/jquery.query-2.1.7.js",async:false}).responseText);
	eval(jQuery.ajax({url:install_dir+"/js/jquery/jquery.getscrollbarwidth.js",async:false}).responseText);
}
// We can wrap conditions round these plugins based on config so we download as we need 

(function($){  
	$.fn.pict = function(options) {  
		//the hook on which to hang pict (cannot really see this being anything other than the body tag...)
		var hook = this;
		if($(hook).length>1){
			throw("You should probably only apply pict to a unique tag to avoid duplication and confusion. We would suggest the body tag.");
			return false;
		}
		var defaults = { install_dir : '/pc', debug : false };  
		var options = $.extend(defaults, options);
		if(options.debug){ //make sure firebug is loaded
		      if(typeof(console) === 'undefined' || console == null)
				options.debug = false;
		}

		//LOAD THE PICT CONFIG FILE
		eval(jQuery.ajax({url:options.install_dir+"/js/pict.config.js", async:false}).responseText);

		var init = function(){
			get_info();
			get_user();
			init_toolbar();
			$(window).resize(function(){
				place_toolbar();
				if($(".pict_window").length>0){
					render_window();
					render_grey_out();
				}
			});
			load_tools();
			render_user_panel();
			toolbar_list();

		};

		/***********************************************************************************************
		 * This prepares requests to the pict.server. If need be it will send them via the pict.proxy. *
		 ***********************************************************************************************/
		 var prepare_request = function(script, post_data){
			//init request object
			var request = {};
			//simplest case the request goes straight to the server
			request.url = pict.protocol+"://"+pict.server+script;
			//The domainid is always added to the request, if we know it and it is not specifically set to false in the post_data
			if(pict.domain.id && post_data.domainid!=false)
				post_data.domainid = pict.domain.id;
			//simplest case the post_data is the post datd
			request.data = post_data;	
			//But are we on a different domain to the pict.server ?
			//If so we need to send our request via a proxy script 
			//which will effectively allow cross domain ajax to happen
			if(pict.server.search(document.domain)<0){
				//the request.utl becomes the proxy on this domain
				request.url = pict.protocol+"://"+pict.domain.this_domain+pict.cd_proxy;
				//This is sent with data that includes the address of the request to the pict.server
				request.data = {};
				request.data.url = encodeURI(pict.protocol+"://"+pict.server+script);
				//The session id
				request.data.domain_session = $.cookies.get("pict_dom");
				//The post data in the form of a JSON string
				request.data.data =  JSON.stringify(post_data);
			}

			return request;
		};
		/********************************************************************************
		 * Forwarding... keep a user logged in when skipping between community websites *
		 *******************************************************************************/
		forward = function(uri,dest_domainid){
			
			var forward_url = pict.protocol+"://"+pict.server+"/pict.forward.php?URL="+uri+"&domain_session="+encodeURIComponent($.cookies.get("pict_dom"))+"&dest_domainid="+dest_domainid;
			document.location = forward_url;
			return false;
		};

		/*******************************************************************************************************
		 * These functions collect info both from the page itself and then from the pict_server about the page *
		 *******************************************************************************************************/
		//Does this page have a persistent identifier and can we access it (probably not)
		var get_pid = function(){
			//lets start with the doi via a dc meta tag
			if($("meta[name=dc.identifier]").length>0)
				return $("meta[name=dc.identifier]").attr("content");
			return false;
		};
		//Combined two functions and two server scripts into a one stop domain/resource info getter
		//First it creates two objects one for the domain in general and one for the particular resource
		var get_info = function(){
			//we do not want the hash part of the url so using the following
			var uri_str = location.protocol+"//"+
					location.host+
					location.pathname;
					if($.query.toString().length) uri_str+=$.query.toString();

/*			var uri_str = $.url.attr("protocol")+"://"+
					$.url.attr("host")+
					$.url.attr("path");
					if($.url.attr("query")) uri_str+="?"+$.url.attr("query");
*/
			pict.resource = {
				pid: get_pid(), //persistent id ?
//				url: $.url, //use the useful jquery url object
				uri_str: uri_str, //but keep a simple record too
				title: $("title").text(),
				id: false //this may be set by info.php request
			};
	
			pict.domain = {this_domain: document.domain, id: false};
			
			//now to get see if pict knows about this resource...
			var request = prepare_request("/pict.info.php", {domain: pict.domain.this_domain, uri_str: pict.resource.uri_str, pid : pict.resource.pid});
			$.ajax({
				type: "POST",
				url: request.url,
				data: request.data,
				async: false,
				success: function(xml){
					if($("pict domainid",xml).length==0){
						throw("This domain is not registered with the PICT server this should be remedied before continuing");
						return false;
					}
					pict.domain.id = $("pict domainid",xml).text();
					if($("pict resourceid",xml).length>0){
						pict.resource.id = $("pict resourceid",xml).text();
						if(options.debug) console.log("Resource id received: "+pict.resource.id);
					}
					if(options.debug) console.log("Domain id received: "+pict.domain.id);
				},
				error: function (data, statusText, e){
					if(options.debug) console.log("Error ("+statusText+") from request: "+request.url+"==>"+dump(request.data));
				}
			});		
		};
		put_resource_info = function(){
			var data = {uri_str: pict.resource.uri_str, action: "put", resource_title: pict.resource.title};
			if(pict.pid)
				data.pid = pict.resource.pid;

			var request = prepare_request("/pict.info.php",data);
			if(options.debug) console.log("putting resource: "+pict.resource.uri_str);
			$.ajax({
				type: "POST",
				url: request.url,
				data: request.data,
				async: false,
				success: function(xml){
					if($("pict resourceid", xml).length>0){
						pict.resource.id = $("pict resourceid", xml).text();
						if(options.debug) console.log("put resource: "+pict.resource.id);
					}
				},
		                error: function (data, statusText, e){
					if(options.debug) console.log("Error ("+statusText+") from request: "+request.url+"==>"+dump(request.data));
		                }
			});
		}

		/**************************************************************************************************************************************
		 * The get user function will return a logged in user if there is one. Either way it sends some vital session data to the pict server *
		 **************************************************************************************************************************************/
		// This function may get overiden by a pict access plugin
		get_user = function(){
			__get_user();
		};
		// A magic link from another pict domain will have a session id with it that can unlock the user data. 
		// (its as secure as passing session ids in url is ?)
		magic_link = function(){
			var domain_session = $.query.get("domain_session");
			if(domain_session){ //we may have come via magic link
				domain_session = decodeURIComponent(domain_session);
				if(pict.server.search(document.domain)<0){
					$.cookies.set("pict_dom",domain_session);
				}else{
					var session_arr = domain_session.split("=");
					var session_name = session_arr[0]+'';
					session_name = session_name.toUpperCase();
					var session_id = session_arr[1];
					$.cookies.set(session_name,session_id);	
				}
				var query_str = $.query.REMOVE("domain_session").toString();
				var here = location.protocol+"//"+
					location.host+
					location.pathname;
					if(query_str) here += query_str;
				//reload the page with the session appended and if the link really was magic we will be logged in
				window.location.href = here;
			}else{
				return false;
			}
		};
		// get the user info from the pict_server. If user not logged on just session data is returned.
		__get_user = function(){
			if(!magic_link()){	
				var request = prepare_request("/pict.access.php",{});
				$.ajax({
					type: "POST",
					url: request.url,
					data: request.data,
					async: false,
					success: function(xml){
						//set session
						if($("pict_user", xml).length>0){
							pict.user = {
								id : $("pict_user userid", xml).text(),
								email : $("pict_user email", xml).text(),
								fullname : $("pict_user fullname", xml).text(),
								login_method : $("pict_user login_method", xml).text()
							};
							if(options.debug) console.log("Have a user with id: "+pict.user.id);
						}else{
							if($("pict native_user", xml).length>0){
								pict.assoc_user = $("pict native_user", xml);
							}
						}
						pict.session_name = $("pict domain_session session_name", xml).text();
						pict.session_id = $("pict domain_session session_id", xml).text();
						$.cookies.set("pict_dom",pict.session_name+"="+pict.session_id);
						if(options.debug) console.log("Session cookie set: "+$.cookies.get("pict_dom"));
					},
			                error: function (data, statusText, e){
						if(options.debug) console.log("Error ("+statusText+") from request: "+request.url+"==>"+dump(request.data));
			                }
				});
			}
		};
		/********************************************
		 * Functions for rendering the pict toolbar *
		 ********************************************/
		// First off, create the tool bar html This is done in accordance to the tab_position values defined in pict.config.js
		// possible values for tab_position 
		// x : r (right), l (left), m (middle)
		// y : t (top), b (bottom), m (middle)
		// the x-y pairing will correspond to ids that are used to define style rules in /css/pict.css
		init_toolbar = function(){
			var tab_text_arr = pict.tab_text.split("");
			var toolbar_id = 'pict_tool_'+pict.tab_position.y+'-'+pict.tab_position.x;
			$(hook).append('<div id="'+toolbar_id+'" class="pict_tool_cont"></div>');
			//If the position is m-b then we invert the placement of the tab and tool bar
			var toolbar = $('<div class="pict_toolbar">&nbsp;<ul class="pict_toolbar_list"></ul></div><div class="pict_tab"></div>');
			if(pict.tab_position.x == "m" && pict.tab_position.y == "b") 
				toolbar = $('<div class="pict_tab"></div><div class="pict_toolbar">&nbsp;<ul class="pict_toolbar_list"></ul></div>');
			//Append the toolbar
			$("#"+toolbar_id).append(toolbar);
			$(".pict_toolbar").prepend('<p class="pict_blurb">'+pict.toolbar_blurb+'</p>');
			//If the tab_position.x is m the tab will need centered, so lets wrap our tab in another div
			if(pict.tab_position.x == "m") $(".pict_tab").wrap('<div class="pict_tab_cont"></div>');
			//The status of the toolbar (open or closed) is held in this var
			pict.tab_open = false;
			//The width of the tab will be dictacted by the tab text length, the tab text is broken into chars (it might end up vertical you see)
			var tab_width=0;
			for(var i=0; i<tab_text_arr.length; i++){
				var ch = tab_text_arr[i];
				if(tab_text_arr[i]==" ") ch = "&nbsp;"
				var em = $("<em>"+ch+"</em>");
				tab_width += $(".pict_tab em").outerWidth();
				$(".pict_tab").append(em);
			}
			$(".pict_tab").width(tab_width);
			//There is an exception if the tab is positioned in the middle of the y axis the text will run vertically and width comes from config
			if(pict.tab_position.y=="m"){
				$(".pict_tab").width(pict.vertical_tab_width);
			}
			//Now place the toolbar
			place_toolbar();
			//and show it
			$("#"+toolbar_id).css({opacity: 1, filter:"alpha(opacity=100)"});
			//hover behaviour for the tab
			$(".pict_tab").hover(function(){
				$(this).css({opacity:1, filter: "alpha(opacity=100)"});
			}, function(){
				if(!$("#"+toolbar_id).hasClass('open'))
					$(this).css({opacity:0.4, filter: "alpha(opacity=40)"});
			});
		}
		// Function for placing the tool bar on the page as per the pict.tab_position
		place_toolbar = function() {

			var toolbar_id = 'pict_tool_'+pict.tab_position.y+'-'+pict.tab_position.x;
			//set toolbar width
			if(pict.tab_position.x != "m") $(".pict_toolbar").width($(window).width()-$(".pict_tab").outerWidth());
			if(pict.tab_position.y == "m") $(".pict_toolbar").width(pict.vertical_toolbar_width);
			else $(".pict_toolbar").height($(".pict_tab").height());
			
		
			var window_h = $(window).height();
			var window_w = $(window).width();
			var tool_h = $("#"+toolbar_id).outerHeight();
			var tool_w = $("#"+toolbar_id).outerWidth();
			var tab_h = $(".pict_tab").outerHeight();
			var tab_w = $(".pict_tab").outerWidth();
			var toolbar_h = $(".pict_toolbar").outerHeight();
			var toolbar_w = $(".pict_toolbar").outerWidth();
			var scrollbar_w = $.getScrollbarWidth();

			//top pos for tools
			if(pict.tab_position.y == "t"){
				var tool_top = 0;
				var ani_top = 0;
				if(pict.tab_position.x == "m") tool_top -= toolbar_h;
			}
			//bottom pos for tools
			if(pict.tab_position.y == "b"){
				var tool_top = window_h-tab_h;
				var ani_top = tool_top;
				if(pict.tab_position.x == "m"){
					tool_top = window_h;
					ani_top -= tab_h-1;
				}
			}
			//middle (y) pos for tools
			if(pict.tab_position.y == "m"){
				var tool_left = 0-toolbar_w;
				var tool_top = 0;
				var ani_top = 0;
				var toolbar_top = (window_h/2) - (tab_h/2);
				$(".pict_toolbar").height(window_h);
				$(".pict_tab").css({position: "relative", top: toolbar_top});
			}
			$("#"+toolbar_id).css({position: "relative"});
			//move tools along the y axis first
			if(pict.tab_position.x == "m"){
//				$("#"+toolbar_id).css({position: "fixed", width: (window_w)});
				$("#"+toolbar_id).css({width: (window_w)});
				if(!pict.tab_open){
					 $("#"+toolbar_id).css({top: tool_top});
					if(options.debug) console.log("top(1): "+tool_top);
				}
			}else{
				if($.browser.msie){ //possibly only need this version 6...?
					if(options.debug) console.log("position not relative");
					 $("#"+toolbar_id).css({position: "absolute", top: tool_top, width: (toolbar_w+tab_w)});
					if(options.debug) console.log("top(2): "+tool_top);
				}else{
					if(options.debug) console.log("top(3): "+tool_top);
					 $("#"+toolbar_id).css({position: "fixed", top: tool_top, width: (toolbar_w+tab_w)});
				}
//				 $("#"+toolbar_id).css({top: tool_top, width: (toolbar_w+tab_w)});

			}

			//redo special case as affected by pos window height change
			if(pict.tab_position.y == "b" && pict.tab_position.x == "m"){
				if(pict.tab_open){
					if(options.debug) console.log("top(4): "+($(window).height()-tool_h));
					$("#"+toolbar_id).css({top: ($(window).height()-tool_h)});
				}else{
					if(options.debug) console.log("top(5): "+($(window).height()-tab_h));
					$("#"+toolbar_id).css({top: ($(window).height()-tab_h)});
				}
				ani_top =$(window).height() -tool_h;
				tool_top =$(window).height() -tab_h;
			}else{
				if(options.debug) console.log("top(6): "+tool_top);
			}

			// now the x axis
			// left pos for tools
			if(pict.tab_position.x == "l"){
				var tool_left= 0-toolbar_w;
				var ani_left=  0;
			}
			//right pos for tools
			if(pict.tab_position.x == "r"){
				var tool_left = window_w-tab_w;
				var ani_left = 0;
			}
			//middle (x) pos for tools
			if(pict.tab_position.x == "m"){
				var tool_left = 0;
				var ani_left = 0;
			}
			//special case for awkward middle right
			if(pict.tab_position.y == "m" && pict.tab_position.x == "r"){
				var tool_left = $(window).width()-$(".pict_tab").fullWidth();
				var ani_left = tool_left-toolbar_w;
			}
			if(options.debug) console.log("scrollbar_w: "+scrollbar_w);

			//Now move the toolbar along the x axis
			if(!pict.tab_open && pict.tab_position.x != "m"){
				$("#"+toolbar_id).css({left: tool_left});
				if(options.debug) console.log("left*: "+tool_left);
			}else if(pict.tab_position.x == "r" && pict.tab_position.y =="m"){
				$("#"+toolbar_id).css({left: tool_left-toolbar_w});
				if(options.debug) console.log("left: ("+tool_left+"-"+toolbar_w+")");
			}
			//Set the toggle action for the tab
			$(".pict_tab").unbind("click");
			$(".pict_tab").toggle(function(){
				$("#"+toolbar_id).animate({top: ani_top, left: ani_left}, 500).addClass('open');
				$(this).css({opacity:1, filter: "alpha(opacity=100)"});
				pict.tab_open = true;
			},function(){
				$("#"+toolbar_id).animate({top: tool_top, left: tool_left}, 500).removeClass('open');
				$(this).css({opacity:0.4, filter: "alpha(opacity=40)"});
				pict.tab_open = false;
			});


		};
		//parts of the place_toolbar stuff to be run after load_tools and render_user_panel etc
		toolbar_list = function(){
			if(pict.tab_position.y=="m")
				$(".pict_toolbar_list li").css({display: 'block'});
		}
		/***************************
 		* Load tools as per config *
 		***************************/
		load_tools = function(){
			if($("#pict_tools_list").length==0){
				$(".pict_toolbar_list").append('<li><ul id="pict_tools_list"></ul></li>');
			}
			for (var i in pict.elements){
				if(!pict.elements[i].enabled)
					continue;
				var tool_name = pict.elements[i].name;
				var tool_options = pict.elements[i].options;
				//get the code
				eval(jQuery.ajax({url:options.install_dir+"/js/pict."+tool_name+".js", async:false}).responseText);
				//create the tool object
				eval("pict."+tool_name+" = new "+tool_name+"(tool_options);");
				//initialise the tool
				var li = $('<li><input type="submit" class="button" id="pict_'+tool_name+'" value="'+ucfirst(tool_name)+'"/></li>');
				$("#pict_tools_list").append(li);
				$("#pict_"+tool_name).click(function(){
					render_window();
					var this_tool = $(this).attr("id").split("pict_")[1];
					eval("pict."+this_tool+".init();");
				});
			}
		};
		ucfirst = function(str){
			var new_str = str.substr(0, 1).toUpperCase() + str.substr(1);
			return new_str;
		}

		/**********************************************************
 		* Functions for rendering the PICT window and its friends *
 		***********************************************************/
		//create the pict_window (to the body tag not the hook even though the hook is likely to be the body tag)
		render_window = function(){
			var v_top = ($(window).height()/2)-(pict.window.height/2);
			var v_left = ($(document).width()/2)-(pict.window.width/2);
			var v_close_top = ($(window).height()/2)-(pict.window.height/2);
			var v_close_left = ($(document).width()/2)-(pict.window.width/2)+ pict.window.width;
			if(options.debug) console.log("v_top: "+v_top+" v_left: "+v_left+" v_close_top: "+v_close_top+" v_close_left: "+v_close_left);

			if(!$(".pict_window").length){
				var pict_window = $('<div class="pict_window" id="pict_'+pict.active+'_window">'+
					'<div class="pict_window_tools"></div>'+
					'<div class="pict_window_content"></div>'+
					'</div>');
				//set width and height as per config and hide
				$(pict_window).css({
					'width' : pict.window.width, 
					'height' : pict.window.height
				}).hide();

				$("body").append(pict_window);
				//create, position and append the close window icon
				var window_closer = $('<div class="pict_window_close">&nbsp;</div>');
				$("body").append(window_closer);
				$(".pict_window_close").click(function(){
					close_window();
				});
				render_grey_out();
				show_window();
			}
			if($.browser.msie) $(".pict_window, .pict_window_close").css({position : 'absolute'});
			$(".pict_window").css({'top' : v_top,'left' : v_left});
			$(".pict_window_close").css({ top: v_close_top-15, left: v_close_left-15});
		};
		//(create), position (and append) the greyout div
		render_grey_out = function(){
			var m_left = parseInt($("body").css("margin-left").replace("px",""));
			var m_right = parseInt($("body").css("margin-right").replace("px",""));


			if(!$(".pict_greyout").length){
				var grey_out = $('<div class="pict_greyout">Greyout div</div>');
				$(grey_out).css({
					top: 0,
					left: 0-m_left,
					opacity: 0.4, 
					filter: 'alpha(opacity=40)', 
					'background-color': "#000"}).hide();
				$("body").append(grey_out);
			}
			$(".pict_greyout").css({width: $(document).width()+m_right, height: $(document).height()});
		};
		show_window = function(){
			$(".pict_window").fadeIn();
			$(".pict_greyout").fadeIn();
		};
		hide_window = function(){
			$(".pict_window").fadeOut();
			$(".pict_greyout").fadeOut();
		};
		close_window = function(closeid){
			$(".pict_window").fadeOut(function(){
				$(this).remove();
			});
			$(".pict_greyout").fadeOut(function(){
				$(this).remove();
				if(closeid){
					pict.active = undefined;
					if(pict.element!=closeid && pict.element != "bookmark"){ //special case for bookmark
						eval("pict."+pict.element+"();");
					}
				}
			});
			$(".pict_window_close").fadeOut();
		};
		/****************************************************************
		* Login functions						*
		****************************************************************/
		// keep your options open...
		login_options = function(target){
			pict.login_target = false;
			if(target)// try and get back to this element given a successful login
				pict.login_target = target;
			if($(".pict_window").length==0) render_window(); 
			$(".pict_window_tools").html("");
			$(".pict_window_content").html("");
			// login via openid provider
			login_openid();
			// just a normal old direct login to a PICT account
			__login();
			// Login to the website we are on (requires plugin for communication between pict_server and the domain system)
			// So far only possible for EPrints
			if(pict.PLUGEE){
			  	$(".pict_window_content").append('<fieldset><legend>Sign-in using your '+pict.PLUGEE+' account</legend>'+
								'<label for="pict_login">&nbsp;</label>'+
								'<input type="submit" value="Sign-in" class="button" id="pict_login"/>&nbsp;<small>(Takes you to the '+pict.PLUGEE+' sign-in page)</small>'+
								'</fieldset>');
				$("#pict_login").click(function(){
					login();
				});
			}
			// Already logged on to PICT on another domain 
			// Fires up a window to check thisi.. 
		  	$(".pict_window_content").append('<fieldset><legend>I am already logged on to PICT</legend>'+
							'<small>Use the button below to verify that you are already '+
							'logged onto PICT via another community website (with <b>this</b> browser).</small>'+
							'<p><input type="submit" class="button" id="pict_verify" value="Verify"/>'+
							'&nbsp;<small>(Opens a popup window)</small></p></fieldset>');
			$("#pict_verify").click(function(){
				check_siblings();
				pict.checked=0;
				check_auth_status();
			});
			// Show window if it is not already visible
			if(!$(".pict_window").is(":visible")) show_window();	
		};
		//login wrapper for domain auth plugin
		login = function(email){
			__login(email);
		}
		//real login (direct to pict account)
		__login = function(email,assoc_identifier,assoc_method){
			$(".pict_window_content").append('<form action="./pict.access.php" method="post" '+
							'id="pict_login_form" name="pict_login_form">'+
							'<fieldset id="pict_login_fs"></fieldset></form>');
			//email passed in so we are on a confirm login page.
			if(assoc_identifier){
				$("#pict_login_fs").append('<legend>PICT log on</legend>'+
							'<label for="email">Email: </label>'+
							'<input class="input" name="email" type="text" value="'+email+'"/>'+
							'<span class="login_error" id="email_mess"></span><br/>'+
							'<input name="assoc_identifier" type="hidden" value="'+assoc_identifier+'"/>'+
							'<input name="assoc_method" type="hidden" value="'+assoc_method+'"/>'+
							'<input name="mode" type="hidden" value="associate"/>');
				$(".pict_window input[name=email]").keyup(function(){
					$(".pict_window legend span").text($(".pict_window input[name=email]").val());
				});
			}else if(email){
				$("#pict_login_fs").append('<legend>Confirm login for '+email+'</legend>'+
							'<input name="email" type="hidden" value="'+email+'"/>'+
							'<span class="login_error" id="email_mess"></span>'+
							'<input name="mode" type="hidden" value="confirm"/>');
			}else{
				$("#pict_login_fs").append('<legend>Sign-in using PICT account</legend>'+
							'<label for="email">Email: </label>'+
							'<input class="input" name="email" id="email"/>'+
							'<input name="mode" type="hidden" value="authenticate"/>'+
							'<span class="login_error" id="email_mess"></span><br/>');
			}

			$("#pict_login_fs").append('<label for="password">Password: </label>'+
						'<input class="input" type="password" name="password" id="password"/>'+
						'<span class="login_error" id="password_mess"></span><br/>'+
						'<label>&nbsp;</label><input class="button" type="submit" value="Sign-in"/>&nbsp;');
			if(!assoc_identifier)
				$("#pict_login_fs").append('<small> OR <a href="#" id="pict_reg">create a new PICT account</a></small>');

			$("#pict_login_fs").append('<input type="hidden" name="method" value="pict"/>');

			$("#pict_reg").click(function(){ render_reg_form(); return false;});
			$("#pict_login_form").submit(function(){
				$(".login_error").html("");
				var data = {email : $(this).find("input[name='email']").val(),
					password : $.md5($(this).find("input[name='password']").val()),
					mode : $(this).find("input[name='mode']").val(),
					method : "pict",
					assoc_method: assoc_method };
				if($(this).find("input[name='assoc_identifier']").length>0)
					data.assoc_identifier = $(this).find("input[name='assoc_identifier']").val();

				var request = prepare_request("/pict.access.php",data);
				$.ajax({
					type: "POST",
					url: request.url,
					data: request.data,
					async: false,
					success: function(xml){
						if($("pict pict_response", xml).text().search("authenticated")==0){
							if($("pict_user", xml).length>0){
								pict.user = {id : $("pict_user userid", xml).text(),
									email : $("pict_user email", xml).text(),
									fullname : $("pict_user fullname", xml).text(),
									login_method : $("pict_user login_method", xml).text()};
								if(pict.login_target){
									eval("var target_object = pict."+pict.login_target);
									target_object.init();
								}else{
									close_window();
								}
								render_user_panel();
								register_daddy();
							}else{
								if(options.debug) console.log("User data not returned: "+request.url+"==>"+dump(request.data));
							}
						}else{
							if($("pict pict_response", xml).text().search("wrong_password")==0)
								$("#password_mess").html("Incorrect password");
							if($("pict pict_response", xml).text().search("no_user")==0)
								$("#email_mess").html("Email not found");
						}
					},
			                error: function (data, statusText, e){
						if(options.debug) console.log("Error ("+statusText+") from request: "+request.url+"==>"+dump(request.data));
			                }
				});		
				return false;
			});	
		};
		//render login for openid
		login_openid = function(assoc_identifier){
			if(assoc_identifier)
				$(".pict_window_content").append("<p>You must log on to your existing PICT account to associate "+assoc_identifier+".</p>");

			$(".pict_window_content").append('<form action="./pict.access.php" method="post" '+
								'id="pict_openid_login_form" name="pict_openid_login_form"></form>');
			$('#pict_openid_login_form').openid();
			$('#pict_openid_login_form').wrapInner('<fieldset id="pict_openid_login_fs"></fieldset>');
			if(assoc_identifier){
				$("#pict_openid_login_fs").append('<legend>OpenID log on</legend>');
			}else{
				$("#pict_openid_login_fs").append('<legend>Use one of these OpenID providers to access PICT</legend>');
			}
			$("#openid_btns").append("<small>(Opens a popup window)</small>");
			$("#pict_openid_login_fs").append('<input type="hidden" name="method" value="openid"/>');

			$("#pict_openid_login_form").submit(function(){
				var openid_request = pict.protocol+"://"+pict.server+"/pict.access.php?method=openid&openid_identifier="+$("input[name='openid_identifier']").val()+"&domainid="+pict.domain.id+"&domain_session="+encodeURIComponent(pict.session_name+"="+pict.session_id);
				if(assoc_identifier) openid_request += "&mode=associate&assoc_identifier="+assoc_identifier;
				else openid_request += "&mode=authenticate";
				var winRef = window.open(openid_request, 'openid_popup', 'width=790,height=580,directories=no,location=no,menubar=no,scrollbars=no,status=no,toolbar=no');
				pict.checked=0;
				//after our popup does the auth work we can check with the pict_server to see what happened
				check_auth_status(true,assoc_identifier);
				return false;
			});
		}
		check_auth_status = function(openid,assoc_identifier){
			pict.checked++;
			if(pict.checked > pict.openid_tries) // 10x3 gives 30 seconds for person to sign in to openid....
				return false;
			setTimeout(function(){
				var data = { openid_identifier : $("input[name='openid_identifier']").val(),
						method : "openid",
						mode : "check_auth_status" }; //should get a response before the mode is even checked...
				var request = prepare_request("/pict.access.php",data);
				$.ajax({
					type: "POST",
					url: request.url,
					data: request.data,
					async: false,
					success: function(xml){
						if($("pict_response", xml).length){
							if($("pict_response", xml).text().search("authenticated")>=0){
								pict.checked=0;
								pict.user = {id : $("pict_user userid", xml).text(),
									email : $("pict_user email", xml).text(),
									fullname : $("pict_user fullname", xml).text(),
									login_method : $("pict_user login_method", xml).text()};
								if(pict.login_target){
									eval("var target_object = pict."+pict.login_target);
									target_object.init();
								}else{
									close_window();
								}
								render_user_panel();
							}else if($("pict_response", xml).text().search("logged_on_no_assoc")>=0){
						//if we are associating an openid account using another openid account we will ignore the no_assoc response
								if(openid && assoc_identifier){
									check_auth_status(openid,assoc_identifier);
								}else{
									if($("pict native_user", xml).length==0){ //no native_user lets keep trying...
										check_auth_status(openid,assoc_identifier);
									}else{
										pict.assoc_user = $("pict native_user", xml);
										//offer reg form (partly filled in)
										render_reg_form();
										pict.checked=0;
									}
								}
							}else{
								check_auth_status(openid,assoc_identifier);
							}
						}else{
							check_auth_status(openid,assoc_identifier);
						}
					},
			                error: function (data, statusText, e){
						if(options.debug) console.log("Error ("+statusText+") from request: "+request.url+"==>"+dump(request.data));
			                }
				});
			},pict.millisec);
		};
		//render the user info and login links...
		render_user_panel = function(){
			//attach the user panel
			if($("#pict_user_panel").length==0)
			  	$(".pict_toolbar_list").append('<li><ul id="pict_user_panel"></ul></li>');
			if($.browser.msie){ //probably ie6 only
				$("#pict_user_panel").css({left: 15}); //christ alone knows why!
			}
			//no user so add a link to the login options
			if(!pict.user){
			  	$("#pict_user_panel").html('<li><input class="button" type="submit" id="pict_login_options" value="Sign-in"/></li>');
			  	$("#pict_user_panel").append('<li><input class="button" type="submit" id="pict_panel_verify" value="Verify"/></li>');
				$("#pict_login_options").click(function(){
					login_options(false);
				});
				$("#pict_panel_verify").click(function(){
					check_siblings();
					pict.checked=0;
					check_auth_status();
				});
/*
				if(pict.assoc_user){ //TODO work out whether we need this and make it work...
				  	$("#pict_user_panel").html('<li>Associate your '+pict.assoc_user.login_method+' account <input type="submit" class="button" id="pict_assoc_user" value="Go"/></li>');
					$("#pict_assoc_user").click(function(){
						eval("associate_"+pict.PLUGEE+"_user();"); 
					});
				}
*/
			}else{
				var descriptor = pict.user.fullname;
				if(!pict.user.fullname) descriptor = pict.user.email;
	 			$("#pict_user_panel").html('<p id="pict_user_info">Logged on as <a href="#" id="pict_profile">'+descriptor+'</a></p>');
				if($.browser.msie){ //probably ie6 only
					$("#pict_user_info").css({left: 20}); //christ alone knows why!
				}

				$("#pict_user_panel").append('<li><input class="button" type="submit" id="pict_logout" value="Sign-out"/></li>');
				if(pict.PLUGEE && pict.user.login_method.toLowerCase() == pict.PLUGEE.toLowerCase()){
					$("#pict_logout").click(function(){
						logout();
					});
				}else{
					$("#pict_logout").click(function(){
						__logout();
					});
				}
				$("#pict_profile").click(function(){
					render_reg_form();
				});
			}	
		};
		//login wrapper for domain auth plugin
		logout = function(){
			__logout();
		}

		__logout = function(){
			var request = prepare_request("/pict.access.php",{mode: 'cancel'});
			$.ajax({
				type: "POST",
				url: request.url,
				data: request.data,
				async: false,
				success: function(xml){
					pict.user = false;
					pict.login_method = false;
					pict.conf = false;
					pict.assoc_user = false;
					render_user_panel();
					close_window();
				},
		                error: function (data, statusText, e){
					if(options.debug) console.log("Error ("+statusText+") from request: "+request.url+"==>"+dump(request.data));
		                }
			});		
		};

		check_siblings = function(){
			var sibling_request = pict.protocol+"://"+pict.server+"/pict.daddy.php?mode=check_siblings&domain_session="+encodeURIComponent(pict.session_name+"="+pict.session_id)+"&domainid="+pict.domain.id;
			
			var winRef = window.open(sibling_request, 'pict_popup', 'width=790,height=130,directories=no,location=no,menubar=no,scrollbars=no,status=no,toolbar=no');
		};
		register_daddy = function(){
			var daddy_request = pict.protocol+"://"+pict.server+"/pict.daddy.php?mode=register_daddy&domainid="+pict.domain.id+"&domain_session="+encodeURIComponent(pict.session_name+"="+pict.session_id);
			var winRef = window.open(daddy_request, 'pict_popup', 'width=790,height=130,directories=no,location=no,menubar=no,scrollbars=no,status=no,toolbar=no');
		};

		/********************************************************************
 		* Render the registration form for registration and profile editing *
 		*********************************************************************/
		render_reg_form = function(target){
			pict.login_target = false;
			if(target)// try and get back to this element given a successful login
				pict.login_target = target;
			if(!$(".pict_window").length) render_window();	
			if(!$(".pict_window").is(":visible")) show_window();	
			$(".pict_window_tools").html("");
			$(".pict_window_content").html("");
			var method = "pict"; //normal registration
			var button_value = "Create account";
			var legend = 'Create a new PICT account';
			var email = "";
			var fullname = "";
			var password = "";
			var userid = false;
			var mode = "register";
			if(pict.assoc_user){ //registration that associates an existing third party auth account
				method = $("login_method", pict.assoc_user).text();
				button_value = "Get a PICT account";
				legend = 'Associate your OpenID account with PICT';
				email = $("email", pict.assoc_user).text();
				fullname = $("fullname", pict.assoc_user).text();
				userid = $("userid", pict.assoc_user).text();
				existing_account = '<button type="button" class="button" type="submit" id="existing_account">I already have a PICT account</button>';
			}
			if(pict.user){ //updating a profile...
				button_value = 'Save changes';
				legend = "Update you PICT user profile";
				email = pict.user.email;
				fullname = pict.user.fullname;
				userid = pict.user.id;
				mode = "update";
				method = pict.user.login_method;
				existing_account = '';
//				password = pict.user.password; //do not think this available... 
			}
			var reg_form = '<form action="./pict.access.php" method="post" id="pict_reg_form">'+
					'<fieldset>'+
					'<legend>'+legend+'</legend>'+
					'<label for="email">Email: </label>'+
					'<input class="input" name="email" id="email" value="'+email+'"/>'+
					'<span class="login_error" id="email_mess"></span><br/>';

			if(method != 'openid'){ 
				reg_form +=
					'<label for="password">Password: </label>'+
					'<input class="input" type="password" name="password" id="password" value="'+password+'"/><br/>'+
					'<label for="re_password">Retype Password: </label>'+
					'<input class="input retype" type="password" name="re_password" id="re_password" value="'+password+'"/><br/>';
			}
			reg_form +='<label for="fullname" id="fullname_label">Fullname: </label>'+
					'<input class="input" name="fullname" id="fullname" value="'+fullname+'"/><br/>'+
					'<input type="hidden" name="method" value="'+method+'"/>';
			if(method == "openid") reg_form += '<input type="hidden" name="assoc_identifier" value="'+$("identifier", pict.assoc_user).text() +'"/>';
			if(pict.assoc_user && userid) reg_form += '<input type="hidden" name="assoc_identifier" value="'+userid+'"/>';


			reg_form += '<input type="hidden" name="mode" value="'+mode+'"/>'+
					'<label>&nbsp;</label><input class="button" type="submit" value="'+button_value+'"/>';
			if(pict.assoc_user && existing_account) reg_form += existing_account;
			reg_form += '<span class="login_error" id="register_mess"></span>'+
					'</fieldset></form>';
			$(".pict_window_content").html(reg_form);
			if(pict.user || (pict.assoc_user && method== "openid")) $("#pict_reg_form input[type=password]").attr("disabled","disabled").addClass("disabled");
			$("#existing_account").click(function(){
				$(".pict_window_content").html("");
				if(method == 'openid') assoc_id = $("identifier", pict.assoc_user).text();
				if(method == 'eprints') assoc_id = userid;
				login_openid(assoc_id);
				__login(email,assoc_id,method);
				return false;
			});
			$("#pict_reg_form").validate({
			   errorClass: "login_error",
			   errorElement: "span",
			   rules: { email: { required: true, email: true },
			     	    password: { required: true, minlength: 5 },
			   	    re_password: { required: true, equalTo: "#password" } },
			   messages :{ email: {email: "Email must be valid"},
					password: {minlength: $.validator.format("Enter at least {0} characters.")},
					re_password : {	equalTo : "Password mismatch"} },
			   submitHandler: function(form){
				var data = {};
				$("form input").each(function(){
					if(!$(this).is(".disabled") && !$(this).is(".retype")){
						var name = $(this).attr("name")+'';
						if(name){
							if(name == 'password')	data[name] = $.md5($(this).val());
							else data[name] = $(this).val();
						}
					}
				});
	
				var request = prepare_request("/pict.access.php",data);
				$.ajax({
					type: "POST",
					url: request.url,
					data: request.data,
					async: false,
					success: function(xml){
						if($("pict_response", xml).text().search("authenticated")==0 || 
						$("pict_response", xml).text().search("updated")==0){
							if($("pict_user", xml).length>0){
								pict.user = {id : $("pict_user userid", xml).text(),
									email : $("pict_user email", xml).text(),
									fullname : $("pict_user fullname", xml).text(),
									login_method : $("pict_user login_method", xml).text()};	
								if(pict.login_target){
									eval("var target_object = pict."+pict.login_target);
									target_object.init();
								}else{
									close_window();
								}
								render_user_panel();
								if($("pict_response", xml).text().search("authenticated")==0) register_daddy();
							}else{
								if(options.debug) console.log("User data not returned: "+request.url+"==>"+dump(request.data));
							}
						}else{
							if($("pict pict_response", xml).text().search("email_exists")>=0){
								$("#email_mess").html("Sorry, email already registered");
								$("#email_mess").fadeIn();
								$("#register_mess").html('<input type="submit" class="button password_reminder" value="Request password reminder"/>');
								$("#register_mess").fadeIn();
								$(".password_reminder").click(function(){
									alert("Have you checked down the back of the sofa...?");
									return false;
								});
							}
							if($("pict pict_response", xml).text().search("not_updated")>=0){
								$("#register_mess").html('Profile not updated');
								$("#register_mess").fadeIn();
							}

							if($("pict pict_response", xml).text().search("error")>=0)
								$("#register_mess").html($("pict pict_response", xml).text());
						}
					},
			                error: function (data, statusText, e){
						if(options.debug) console.log("Error ("+statusText+") from request: "+request.url+"==>"+dump(request.data));
			                }
				});		
				return false;
			   }
			});
		};	
		/***********************************************************************
 		* Utility functions for functional utility (The tin says what they do) *
 		************************************************************************/
		function dump(obj) {
			var out = '';
    			for (var i in obj) {
				out += i + ": " + obj[i] + "\n";
			}
			return out;
		}
		getScrollerWidth = function () {
		    	var div = $('<div style="width:50px;height:50px;overflow:hidden;position:absolute;top:-200px;left:-200px;"><div style="height:100px;"></div>');
		    	// Append our div, do our calculation and then remove it
		    	$('body').append(div);
			var w1 = $('div', div).innerWidth();
			div.css('overflow-y', 'scroll');
			var w2 = $('div', div).innerWidth();
			$(div).remove();
			return (w1 - w2);
		};
/*
		getScrollerWidth = function() {
		    	var scr = null;
		    	var inn = null;
		    	var wNoScroll = 0;
		    	var wScroll = 0;

		    	// Outer scrolling div
			scr = document.createElement('div');
			scr.style.position = 'absolute';
			scr.style.top = '-1000px';
			scr.style.left = '-1000px';
			scr.style.width = '100px';
			scr.style.height = '50px';
			//Start with no scrollbar
			scr.style.overflow = 'hidden';
			//Inner content div
			inn = document.createElement('div');
			inn.style.width = '100%';
			inn.style.height = '200px';
			//Put the inner div in the scrolling div
			scr.appendChild(inn);
			//Append the scrolling div to the doc
			document.body.appendChild(scr);
			//Width of the inner div sans scrollbar
			wNoScroll = inn.offsetWidth;
			//Add the scrollbar
			scr.style.overflow = 'auto';
			//Width of the inner div width scrollbar
			wScroll = inn.offsetWidth;
			//Remove the scrolling div from the doc
			document.body.removeChild(document.body.lastChild);
			//Pixel width of the scroller
			return (wNoScroll - wScroll);
		};
		detectScrollbar = function(){
			var vHeight = 0;
			if (document.all) {
				if (document.documentElement) vHeight = document.documentElement.clientHeight;
				else vHeight = document.body.clientHeight;	
			}else vHeight = window.innerHeight;
			//if (document.body.offsetHeight > vHeight)
			var doc_height = $("body").fullHeight();
			if (doc_height > vHeight) return true;
			return false;
		};
*/
		/*************************************************************
		* Pull in plugin code for interaction with the domain system *
		*************************************************************/
		// Overriding some functions... although the originals should be still available via the __function_name();
		if(pict.PLUGEE){
		        eval(jQuery.ajax({url:options.install_dir+"/js/plugins/"+pict.PLUGEE+".js", async:false}).responseText);
		}		

		/******************
		* Okay lets go... *
		******************/
		return this.each(function() {  
			init();
		});  

	};  
	//A height that includes margins...
	jQuery.fn.fullHeight = function() {
	    	var o = $(this[0]) // It's your element
		var paddingHeight  = 0;
		eval("var marginHeight = "+$(o).css("margin-top").replace("px","")+" + "+$(o).css("margin-bottom").replace("px",""));
	
		return (o.outerHeight() + (marginHeight*2));
	};
	//A width that includes margins...
	jQuery.fn.fullWidth = function() {
	    	var o = $(this[0]) // It's your element
		var paddingWidth  = 0;
		eval("var marginWidth = "+parseInt($(o).css("margin-left").replace("px",""))+" + "+parseInt($(o).css("margin-right").replace("px","")));
		eval("var paddingWidth = "+parseInt($(o).css("padding-left").replace("px",""))+" + "+parseInt($(o).css("padding-right").replace("px","")));
		if(isNaN(marginWidth))
			marginWidth = 0;
		return (o.width() + marginWidth + paddingWidth);
	};
})(jQuery);  

/*********************************/
jQuery(document).ready(function() {  //DOM ready 
	//We do not want pict to slow up the loading of the host page, that might annoy people who are not neccessarily going to use it.
	//If pict loading trumps image loading then swap then comment out the load condition
	jQuery(window).bind("load",function(){ //Page fully loaded (inc images). NB any broken images will cause this to never initiate PICT
		//a function (outside the pict extension) for loading our helpful plugins...
		pict_load_plugins();
		//And now we init PICT
		jQuery('body').pict({debug: true});
	});
});

