/////*****/////
var MAIN_DATA = undefined;
var OYF = {};
OYF.VIEWER_FRIEND_CACHE = undefined;
var V_LIBRARY_OS_CONTAINER = opensocial.Container.get();
var MS_OS_TOKEN = MyOpenSpace.MySpaceContainer.OSToken;


/*
============================================================================================
       BEGIN MyOpenSpace.Widgets include.

       Please note that this will be moved to a standard library and
       you should utilize that library once it is announced.
============================================================================================
*/

/**
 * Copyright 2008 Fox Interactive Media
 * This code is provided without warranty.
 * @fileoverview UI widgets and utilities for use with OpenSocial.
 * 
 * @author (Chris Cole) c c o l e  _A@T_  myspace.com 
 */

if(window.MyOpenSpace === undefined){
	MyOpenSpace = {};
}
if(MyOpenSpace.Widgets === undefined){
	MyOpenSpace.Widgets = {version:0.2};
}

/**
 * Collection of utility methods used by the MyOpenSpace.Widgets objects.
 * Look for this to be cleaned up and moved into an external include.
 */
MyOpenSpace.Widgets.Utility = {
	/**
	 * Apply an object-literal style to a DOM element
	 * 
	 * @param {DOMElement} 		element
	 * @param {Style literal} 	style
	 */
	applyInlineStyle: function(element, style){
		if(!element || !style) return;
		
		var styleVal;
		var stylePart;
			for(stylePart in style){
				try{
					styleVal = eval("style." + stylePart);
					eval("element.style." + stylePart + "= \"" + styleVal + "\";");
				}
				catch(ex){
					alert(ex.message + ":\n\n " + stylePart + "\n" + styleVal)
				}
			}
		
	},
	
	/**
	 * Attempts to safely attach an event handler to an element
	 * @param {DOMElement} element				DOM element
	 * @param {String} eventName 				string name of event w/o "on"
	 * @param {function reference} action 		function reference
	 */
	safeAttachEvent: function(element, eventName, action){
		if(!element){
			return;
		}
		if(element.addEventListener){
			element.addEventListener(eventName, action, false);
		}
		else if(element.attachEvent){
			element.attachEvent("on"+eventName, action);
		}
	},
	
	/**
	 * Build a DOM element
	 * @param {string} tag Tag name
	 * @param {Object} contents
	 * @param {object literal} attributes
	 */
	domElement: function(tag, contents, attributes){
		var elem = document.createElement(tag);
		var dbs = 'created dom: ' + tag;
		if(contents){
			dbs += "\n\nwith: \n" + contents.toString()
		}
		if(!!(window.attachEvent && !window.opera)){
			//alert(dbs)
		}

		if(contents){
			if(typeof(contents) == "string"){
				elem.innerHTML = contents;
			}
			else{
				if(contents.length){
					var el;
					for(var i=0; i < contents.length; i++){
						try{
							if (typeof(contents[i]) == "string") {
								var txtNode = document.createElement("span");
								txtNode.innerHTML = contents[i];
								elem.appendChild(txtNode);
							}
							else {
							
								if (contents[i]) {
									elem.appendChild(contents[i])
								}
								else {
									alert('null elem')
								}
							}
						}
						catch(ex){
							alert("dom build failed: " + ex.message)
						}
					}
				}
				else{
					try{
						elem.appendChild(contents);					
					}
					catch(ex){
						alert("single dom build failed: " + ex.message)
					}
				}
			}
		}
		
		if(attributes){
			var val;
			for(var attr in attributes){
				val = eval("attributes." + attr);
				elem.setAttribute(attr, val);
			}
		}		
		return elem;		
	}
}



/**
 * Specialized data structure for storing Friend data.
 * This accepts an opensocial group and builds out a hash
 * plus two binary search trees based on first and last name
 * @param {Object} friendsData
 */
MyOpenSpace.Widgets.FriendList = function(friendsData){
	this._friendsData = null; //OSocial response collection
	
	this.firstNameTree = null;
	this.lastNameTree = null;

	/**
	 * Internal collection of friends, keyed on ID
	 * @param {Object} person
	 */
	this.friendMap = new Array();
	this._pagingFriends	= new Array();
	
	this.initialize(friendsData);
	
}

MyOpenSpace.Widgets.FriendList.prototype = {
	
	/**
	 * Initialize the object with the opensocial friends group
	 * @param {Object} friendsData
	 */
	initialize: function(friendsData){
		this._friendsData = friendsData;
		if(this._friendsData != null){
			var thisRef = this;
			this._friendsData.each(function(friendData){
				thisRef.addFriend(friendData);
			});
			
		}
	},
	
	/**
	 * Get a friend by their ID
	 * @param {Object} id
	 */
	getFriend: function(id){
		return this.friendMap[id];
	},
	
	/**
	 * Find an array of person objects where first or last name
	 * matches the findLike string.
	 * @param {Object} findLike
	 */
	findFriends: function(findLike){
		var results = new Array();
		if(this.firstNameTree != null){
			results = this.firstNameTree.findLike(findLike);
		}
		if(this.lastNameTree != null){
			if(!results){
				results = new Array();
			}
			results = results.concat(this.lastNameTree.findLike(findLike));
		}
		return results;
	},

	/**
	 * Adds a friend to the friendMap
	 * @param {Object} person
	 */
	addFriend: function(person){
		var key = person.getField(opensocial.Person.Field.ID)
		if (key) {
			key = key.toString();
		}
		else {
			alert('no key');
			return;
		}
		
		if (!this.friendMap[key]) {
			this.friendMap[key] = person;
			this._pagingFriends.push(person);
		}
		
		//this is only a sample and not internationalized
		var xName = person.getField(opensocial.Person.Field.NAME);
		if (xName != null && xName.length > 0) {
			var parts = xName.split(" ");
			if (this.firstNameTree == null) {
				this.firstNameTree = new MyOpenSpace.Widgets.FriendList.Node(parts[0], person);
			}
			else {
				this.firstNameTree.addPerson(parts[0], person);
			}
			if (parts.length > 1) {
				var lname = parts[parts.length - 1];
				if (this.lastNameTree == null) {
					this.lastNameTree = new MyOpenSpace.Widgets.FriendList.Node(lname, person);
				}
				else {
					this.lastNameTree.addPerson(lname, person);
				}
			}
		}
	}
}



/**
 * Node in the person binary search tree
 * @param {Object} key
 * @param {Object} person
 */
MyOpenSpace.Widgets.FriendList.Node = function(key, person){
	this.key = key;
	this.person = person;
	this.leftNode = null;
	this.rightNode = null;
	this.parentNode = null;
	this.subNodeCount = 0;  //count of child nodes under this node
	
	/**
	 * Adds a new person to this node tree
	 * @param {Object} key
	 * @param {Object} person
	 */
	this.addPerson = function(key, person){
		if(!key){
			return;
		}
		
		this.subNodeCount++;
		
		if(this.compareTwoPartialKeys_(this.key, key) < 0){
			if(this.rightNode == null){
				this.rightNode = new MyOpenSpace.Widgets.FriendList.Node(key, person);
			}
			else{
				this.rightNode.addPerson(key, person);
			}
		}
		else{
			if(this.leftNode == null){
				this.leftNode = new MyOpenSpace.Widgets.FriendList.Node(key, person);
			}
			else{
				this.leftNode.addPerson(key, person);
			}
		}
	};
	
	/**
	 * Compares this node to another node.
	 * If this node's key is greater return 1,
	 * If this node's key is less return -1,
	 * If node keys are equal (same) return 0.
	 * String comparisons are case insensitive.
	 * @param {Object} node
	 */
	this.compareTo = function(node){
		if(node == null){
			return 1;
		}
		return this.compareTwoPartialKeys_(this.key, node.key);
	};

	/**
	 * Compares a partial string to a main key
	 * and returns -1 if testKey is greater than mainKey,
	 * returns 0 if testKey is equal to first part of mainKey,
	 * returns 1 if mainKey is greater than testKey
	 * @param {String} mainKey
	 * @param {String} testKey
	 */
	this.compareTwoPartialKeys_ = function(mainKey, testKey){
		var a = mainKey.toLowerCase();
		var b = testKey.toLowerCase();
		if(a.length > b.length){
			a = a.substr(0, b.length)
		}
		if(a<b){
			return -1;
		}
		else if(a==b){
			return 0;
		}
		else{
			return 1;
		}
	};

	

	/**
	 * Recursively find all nodes that are a partial key match,
	 * both from firstName and lastName trees.
	 * 
	 * @param {Object} partialKey
	 */
	this.findLike = function(partialKey){
		var results = new Array();
		if(partialKey == null || partialKey.length == 0){
			return results;
		}
		var keyTest = this.compareTwoPartialKeys_(this.key, partialKey);
		if(keyTest == 0){
			results.push(this.person);
		}
		if(this.subNodeCount > 0){
			//test right node if keytest is less or equal to node
			if(keyTest == -1){
				if (this.rightNode != null) {
					results = results.concat(this.rightNode.findLike(partialKey));
				}
			}
			else if (keyTest == 0) {
				if (this.leftNode != null) {
					results = results.concat(this.leftNode.findLike(partialKey));
				}
				if (this.rightNode != null) {
					results = results.concat(this.rightNode.findLike(partialKey));
				}
			}
			else {
				if (this.leftNode != null) {
					results = results.concat(this.leftNode.findLike(partialKey));
				}
			}
		}
		return results;		
	}
}




/**
 * Friend Picker widget using OpenSocial tools.
 * Look for this to be cleaned up and moved into an external include.
 *
 * @author c c o l e  _A@T_  myspace.com (Chris Cole)
 */
MyOpenSpace.Widgets.FriendPicker = function(){
	this.version				= 0.2;
	this.MAX_FRIENDS			= 1000;
	this.currentPage 			= 1;
	this.pageSize				= 4;
	this.dataLoaded				= false;
	this.DOMElement 			= null;
	this._DOMBuilt 				= false;
	this._friendDisplayElem 	= null;
	this._emptyNode 			= document.createTextNode("");
	this._osContainer			= opensocial.Container.get();
	this._popupRetries			= 0;
	this.MAX_RETRIES			= 100;
	this.displayWidth			= "350px";
	this.displayHeight			= "400px";
	this.friendClickAction		= null;
	this.buildSelectedUI		= true;
	
	/**
	 * The opensocial.Person object representing the friend picked by the user.
	 */
	this.selectedFriend			= null;
	
	/**
	 * Internally used catalog of all friends of the user.
	 */
	this.friendsCatalog			= null;

	this._isIE = !!(window.attachEvent && !window.opera); //credit to prototype.js
	
	/**
	 * Internally used DOM id values.  This current design only allows for
	 * one FriendPicker to exist on a page.  We may change the design if this
	 * becomes a problem.
	 */
	this.ElementIDs = {
		pagingLabel: 		'_mys_pageLabel',
		searchBox: 			'_mys_searchTextBox',
		searchResults: 		'_mys_searchResults',
		popTrigger:			'_mys_popTrigger'
	}

	/**
	 * Interally used style definition objects.
	 * In the future
	 */
	this.Styles = {
		styleFriendPickBlock: {
			padding: 	"2px",
			cursor:		"pointer",
			marginTop:	"3px",
			fontSize:	"13pt",
			fontWeight:	"bold",
			minHeight:  "60px",
			maxHeight:  "130px",
			height: "70px",
			zIndex: 10
		},
	
		styleFriendPickImageBlock: {
			align:		"middle"
		},
		
		styleQuickBorder: {
			border:	"1px solid green",
			padding: "4px",
			backgroundColor: "#DDD"
		},

		styleButton: {
			border:	"1px solid #AAA",
			padding: "3px",
			backgroundColor: "#DDD",
			cursor: "pointer",
			width: "18px",
			height: "18px",
			overflow: "hidden",
			textAlign: "center",
			marginRight:"3px",
			fontSize: "7pt",
			fontFamily: "courier, sans-serif"
		},
		
		styleSearchResults: {
			position: "absolute",
			border: "1px solid green",
			height: "200px",
			width: "180px",
			display: "none",
			backgroundColor: "white",
			fontSize: "8pt",
			fontWeight: "normal"
		},
		
		styleTitleBar: {
			borderTop: "1px solid #333",
			borderBottom: "1px double #333",
			fontSize: "6pt",
			paddingLeft: "3px",
			backgroundColor: "#003399",
			color: "#fff"			
		},
		
		stylePopupWindow: {
			position: "absolute", 
			width:this.displayWidth,
			height:this.displayHeight,
			backgroundColor:"#EEE",
			display:"none",
			overflow:"hidden",
			border: "2px solid #CCC"
		}
		
	};
	
	// icons sources
	this.Icons = {
		prev: "http://a454.ac-images.myspacecdn.com/images01/56/m_04c6d68883ac1df9b2dab3db57013845.png",
		next: "http://a142.ac-images.myspacecdn.com/images01/38/m_e7abc35000473693de736157ab6358ad.png",
		close: "http://a609.ac-images.myspacecdn.com/images01/35/m_a6c0aff73a2df676f879728e442895a0.png",
		showgrid: "http://a172.ac-images.myspacecdn.com/images01/116/m_6c186813c7786593d2ccd6cca39fb0f3.png",
		showlist: "http://a809.ac-images.myspacecdn.com/images01/49/m_77ebb6795ff95264bfe73e5f7dfc0b70.png"
	}


	if(arguments.length > 0){
		this.initialize(arguments[0]);
	}

};


MyOpenSpace.Widgets.FriendPicker.prototype = {
	/**
	 * Adds a friend to the friendMap
	 * @param {Object} person
	 */
	addFriend: function(person){
		var key = person.getField(opensocial.Person.Field.ID)
		if (key) {
			key = key.toString();
		}
		else {
			alert('no key');
			return;
		}
		
		if (!this.friendMap[key]) {
			this.friendMap[key] = person;
			this._pagingFriends.push(person);
		}
		else {
//			alert('Double entry');
		}
	},
	
	
	/**
	 * Searches the catalog for a partial match.
	 * Returns an array of people
	 * 
	 * @param {Object} searchString
	 */
	searchFriends: function(searchString){
		var retval = new Array();
		if(this.friendsCatalog == null){
			return retval;
		}
		else{
			return this.friendsCatalog.findFriends(searchString);
		}
	},
	
	
	/**
	 * Load friends via the OpenSocial API request
	 */
	_loadOpenSocialFriends: function(){
		var dataReqObj = this._osContainer.newDataRequest();
		var viewerReq = this._osContainer.newFetchPersonRequest(opensocial.DataRequest.PersonId.VIEWER);
		dataReqObj.add(viewerReq);
		
		var viewerFriendsReq = this._osContainer.newFetchPeopleRequest(opensocial.DataRequest.Group.VIEWER_FRIENDS);
		
		dataReqObj.add(viewerFriendsReq);
		var thisRef = this; // gets around callback context, but only allows one per page
		var callBack = function(dataResponse){
			thisRef._loadOsFriendsDataResponse(dataResponse);
		};
		dataReqObj.send(callBack);
	},
	
	/**
	 * Callback method for loading friends data
	 * @param {Object} dataResponse
	 */
	_loadOsFriendsDataResponse: function(dataResponse){
		var errMsg = '';
		if (dataResponse.hadError()) {
			var data = dataResponse.get(opensocial.DataRequest.Group.VIEWER_FRIENDS);
			//throw "Friends load error: " + data.getErrorCode() + '\n' + data.getErrorMessage();
			errMsg = 'Error in friend load: ' + data.getErrorCode() + '\n' + data.getErrorMessage();
		}

		this.viewerData = dataResponse.get(opensocial.DataRequest.PersonId.VIEWER).getData();
		this._friendsData = dataResponse.get(opensocial.DataRequest.Group.VIEWER_FRIENDS).getData();
		if(this._friendsData == null){
			errMsg += 'No friend data found for picker';
			alert(errMsg);
			return;
		}
		this.friendsCatalog = new MyOpenSpace.Widgets.FriendList(this._friendsData);
		this.dataLoaded = true;
		this._setLoadingMessageDisplay(false);
	},
	
	/**
	 * Construct the initial DOM objects
	 */
	_buildDOM: function(){
		if (!this._DOMBuilt) {
			var makeElem = MyOpenSpace.Widgets.Utility.domElement;
			var styleIt = MyOpenSpace.Widgets.Utility.applyInlineStyle;			

			if (!this.DOMElement) {
				throw "Friend picker must be initialized with a DOM element";
			}
			
			//clear dom element
			while(this.DOMElement.hasChildNodes()){
				this.DOMElement.removeChild(this.DOMElement.lastChild);
			}
			
			try{
				styleIt(this.DOMElement, this.Styles.styleFriendPickBlock)
				styleIt(this._friendDisplayElem, this.Styles.styleFriendPickBlock)
			}
			catch(ex){
				alert("Style error: " + ex)
			}
			
			this.popupWindow = this._buildPopupWindowDOM();
		
			var picker = this._buildPopupPicker();
	
			this.DOMElement.appendChild(picker);

			if (!this._isIE) {
				this.DOMElement.appendChild(this._buildLoadingNotice());
			}
			this.DOMElement.appendChild(this.popupWindow);
			if (this.buildSelectedUI) {
				var selectedUI = makeElem("div", " ", {id:"__selectedFriendDiv"});
				this.DOMElement.appendChild(selectedUI);
			}
						
			this.popupIsOpen = false;
			this._DOMBuilt = true;
		}
	},
	
	/**
	 * Builds the POPUP window ui.
	 */
	_buildPopupWindowDOM: function(){
		var makeElem = MyOpenSpace.Widgets.Utility.domElement;
		var styleIt = MyOpenSpace.Widgets.Utility.applyInlineStyle;
		
		//var titleBar = makeElem("div", "MyOpenSpace.Widgets.FriendPicker - version " + this.version);
		var titleBar = makeElem("div", "HelloTree Friends Selector");
		styleIt(titleBar, this.Styles.styleTitleBar);
		
		var toolbar = this._buildToolbarDOM();
		
		var searchbar = this._buildSearchDOM();

		var fstyle = "width:" + this.displayWidth + ";height:" + this.displayHeight + ";";
		fstyle += "overflow:scroll;"
		this._friendDisplayElem = makeElem("div", "", {style:fstyle});
		var popWindow = makeElem("div", [titleBar, toolbar, searchbar, this._friendDisplayElem] );
		try{
			styleIt(popWindow, this.Styles.stylePopupWindow);
		}
		catch(ex){
			alert('popup style failed: ' + ex.message)
		}
		return popWindow;
	},
	
	_buildSearchDOM: function(){
		var makeElem = MyOpenSpace.Widgets.Utility.domElement;
		var styleIt = MyOpenSpace.Widgets.Utility.applyInlineStyle;
		
		var thisRef = this;
		var action = function(){
			var slem = document.getElementById(thisRef.ElementIDs.searchBox);
			if(!slem){
				alert('missing search box');
				return;
			}
			thisRef.showSearchResults(thisRef.searchFriends(slem.value), slem.value);
		}
		
		var box = makeElem("input", null, 
			{
				id: this.ElementIDs.searchBox,
				type: "text",
				autocomplete: "off",
				disableautocomplete: "true"
			});
			
		MyOpenSpace.Widgets.Utility.safeAttachEvent(box, "keyup", action);
		
		var sresults = makeElem("div", null, 
			{
				id: this.ElementIDs.searchResults,
				type: "text"
			});
		
		styleIt(sresults, this.Styles.styleSearchResults);
		
		
		var elem = makeElem("div", [box, sresults]);
		return elem;
	},
	
	_buildLoadingNotice: function(){
		var makeElem = MyOpenSpace.Widgets.Utility.domElement;
		var styleIt = MyOpenSpace.Widgets.Utility.applyInlineStyle;
		
		var elem = makeElem("div", "Loading Friends ... please wait", 
			{
				id:"__pickerLoadingDiv",
				style:"font-size:8pt;display:none;position:absolute;border:2px solid grey;background-color:#DDD;left:30px;top:35px;"
			}
			
		);
		
		return elem;		
	},
	
	_buildPopupPicker: function(){
		var makeElem = MyOpenSpace.Widgets.Utility.domElement;
		var styleIt = MyOpenSpace.Widgets.Utility.applyInlineStyle;
		
		try{
				
			var elem = makeElem("span", "[Click for recipient]", 
							{
								style:"color:#AAA;font-size:8pt;cursor:pointer;font-weight:bold;padding:2px;",
								id: this.ElementIDs.popTrigger
							}
						);
	
			styleIt(elem, this.Styles.styleQuickBorder);
			var thisRef = this;
			var action = function(){
				thisRef.togglePopup();
			};
			
			elem.onclick = action;
		}
		catch(ex){
			alert('err: ' + ex.message)
		}
		return makeElem("div", elem);
	},
	
	_buildSelectedUIDOM: function(person){
		var makeElem = MyOpenSpace.Widgets.Utility.domElement;
		var styleIt = MyOpenSpace.Widgets.Utility.applyInlineStyle;
		
		var imgSrc = person.getField(opensocial.Person.Field.THUMBNAIL_URL);
		var name = person.getField(opensocial.Person.Field.NAME);
		
		var imgOpts = {id:"__selectedFriendImage", 
								src:imgSrc, 
								align:"top"};
		
		var imgStyle = "height:65px;margin-right:10px;";
		if(this._isIE){
			imgStyle += "width:60px;"
			imgOpts.width = "60";
			imgOpts.height = "65";
		}
		imgOpts.style=imgStyle;

		
		var elem = makeElem("div",
					[
						makeElem("img", null, imgOpts),
						makeElem("span", name, {id:"__selectedFriendName", style: "margin-left:2px;width:140px;overflow:hidden;"})] );
		var thisRef = this;
		elem.onclick = function(){
			thisRef.togglePopup();
		};
		
		return elem;
	},
	
	/**
	 * Builds out the DOM elements for the toolbar
	 */
	_buildToolbarDOM: function(){
		var makeElem = MyOpenSpace.Widgets.Utility.domElement;
		var styleIt = MyOpenSpace.Widgets.Utility.applyInlineStyle;
		
		var prevLink = this._buttonElem_Prev();
		var nextLink = this._buttonElem_Next();
		var gridLink = this._buttonElem_DisplayGrid();
		var listLink = this._buttonElem_DisplayList();
		var closeLink = this._buttonElem_Close();
		
		
		var pgLabel = makeElem("span", null, {id: this.ElementIDs.pagingLabel, style:"font-size:7pt;margin-right:5px;"});
		
		var toolbar;
		
		toolbar = makeElem("div",
						[	prevLink,
							nextLink,
							"  ",
							pgLabel,
							gridLink,
							listLink,
							"    ",
							closeLink
						],
						{style: "border-bottom:1px solid #333;margin-bottom:3px;"}
						);
						
		return toolbar;
	},
	_buttonElem_Image: function(source, imgWidth, imgHeight, text, action){
		var makeElem = MyOpenSpace.Widgets.Utility.domElement;
		
		var opts = {
			src: source,
			width: imgWidth,
			height: imgHeight,
			alt: text,
			title: text
		}
		
		var img = makeElem("img", null, opts);
		
		return this._buttonElem_Generic(img, action);
	},
	
	_buttonElem_Generic: function(face, action){
		var makeElem = MyOpenSpace.Widgets.Utility.domElement;
		var styleIt = MyOpenSpace.Widgets.Utility.applyInlineStyle;

		var button = makeElem("button", face, {style:"width:26px;padding:0;height:20px;"});

		if(action){
			button.onclick = action;
		}
		return button;
	},
	
	_buttonElem_Close: function(){
		var thisRef = this;
		
		var action = function(){
			thisRef.popDown();
		};
		var btn = this._buttonElem_Image(this.Icons.close, 16, 16, "close", action);
		btn.setAttribute("title", "Close");
		return btn;
	},
	_buttonElem_Next: function(){
		var thisRef = this;

		var action = function(){
			thisRef.nextPage();
		};
		var btn = this._buttonElem_Image(this.Icons.next, 16, 16, "next", action);
		btn.setAttribute("title", "Next");
		return btn;
	},
	_buttonElem_Prev: function(){
		var thisRef = this;

		var action = function(){
			thisRef.prevPage();
		};
		var btn = this._buttonElem_Image(this.Icons.prev, 16, 16, "previous", action);
		btn.setAttribute("title", "Prev");
		return btn;
	},
	
	_buttonElem_DisplayGrid: function(){
		var thisRef = this;

		var action = function(){
			alert('Grid display not implemented');
		};
		var btn = this._buttonElem_Image(this.Icons.showgrid, 16, 16, "grid display", action);
		btn.setAttribute("title", "Grid Display");
		return btn;
	},
	_buttonElem_DisplayList: function(){
		var thisRef = this;

		var action = function(){
			alert('List display already active');
		};
		var btn = this._buttonElem_Image(this.Icons.showlist, 16, 16, "list display", action);
		btn.setAttribute("title", "List Display");
		return btn;
	},
	
	/**
	 * Show search results in popup list
	 * @param {Array} results
	 */
	showSearchResults: function(results, searchString){
		var makeElem = MyOpenSpace.Widgets.Utility.domElement;
		var elemID

		var sresults = document.getElementById(this.ElementIDs.searchResults);
		if(!sresults) return;
		
		//clear prior results
		while(sresults.hasChildNodes()){
			sresults.removeChild(sresults.lastChild);
		}
		//add new results
		if(results == null || results.length == 0 ){
			sresults.style.display="none";
			if (this._isIE) {
				sresults.style.visibility="hidden";
			}

			return;
		}
//		var personList = new Array(results.length);
		var person;
		var text;
		var id;
		//var actions = new Array(results.length);
		var action;
		var ediv, action;
		var thisRef = this;
		var re = new RegExp(searchString, "ig");
		for(var i=0; i < results.length; i++){
			person = results[i];
			id = person.getField(opensocial.Person.Field.ID)
			text = person.getField(opensocial.Person.Field.NAME);
			text = text.replace(re, "<b>" + searchString + "</b>");
			action = function(){
				var myid;
				if (thisRef._isIE) {
					var thisElem;
					if(window.event && window.event.srcElement){
						myid = window.event.srcElement.getAttribute("personid");
					}
				}
				else{
					myid = this.getAttribute("personid");
				}				

				if(myid == null){
					return;
				}
				thisRef._setSelectedFriend(myid, thisRef);
				if(window.event){
					window.event.cancelBubble = true;
				}
				thisRef.showSearchResults(null, ''); //clear results window
				var sw = document.getElementById(thisRef.ElementIDs.searchBox);
				if(sw){
					sw.value = "";
				}
				return false;
			};

			ediv = makeElem("div", 
						makeElem("a", text, {
								href: "#",
								style: "text-decoration:none;color:#333;",
								onclick: "return false",
								personid: id
							}),
						{
							style: "margin-bottom:3px;border-top:1px solid #777;",
							personid: id
						}	
			)
			MyOpenSpace.Widgets.Utility.safeAttachEvent(ediv, "click", action);
			
			sresults.appendChild(ediv);
		}		
		
		sresults.style.display="block";
		if (this._isIE) {
			sresults.style.visibility="visible";
		}
	},
	
	/**
	 * Draws friends in the picker
	 * @param {Object} pageNum
	 */
	drawFriendsPage: function(pageNum){
		this.currentPage = Math.max(0, Math.min(pageNum, this.pageCount()));
		if (!this._DOMBuilt) {
			this._buildDOM();
		}
		while (this._friendDisplayElem.hasChildNodes()) {
			this._friendDisplayElem.removeChild(this._friendDisplayElem.lastChild);
		}

		var thisPerson;
		var startPos = Math.min(this.friendsCatalog._pagingFriends.length-1, ((pageNum * this.pageSize) - this.pageSize));
		var endPos = Math.min(this.friendsCatalog._pagingFriends.length-1, ((pageNum * this.pageSize)-1));
		startPos = Math.max(0, startPos);
		for(var i=startPos;i <= endPos; i++){
			thisPerson = this.friendsCatalog._pagingFriends[i];
			this._friendDisplayElem.appendChild(this._getFriendDOM(thisPerson));
		}
		
		var lbl = document.getElementById(this.ElementIDs.pagingLabel);
		if(lbl){
			lbl.innerHTML = "Page " + this.currentPage + " of " + (this.pageCount());
		}
	},
	
	/**
	 * Number of pages of data in the friends list
	 */
	pageCount: function(){
		var pages = Math.floor(this.friendsCatalog._pagingFriends.length / this.pageSize);
		if(this.friendsCatalog._pagingFriends.length % this.pageSize > 0){
			pages++;
		}
		return pages;
	},
	
	/**
	 * Display a "still loading" message if a user attempts to activate prior to picker
	 * loading friend data.
	 * 
	 * @param {Object} visible
	 */
	_setLoadingMessageDisplay: function(visible){
			var elem = document.getElementById("__pickerLoadingDiv");
			if(elem){
				if(visible){
					elem.display="block";
				}
				else{
					elem.disabled="none";
				}
			} 
	},
	
	/**
	 * Toggle display of a popup on or off.
	 */
	togglePopup: function(){
		if(!this.popupIsOpen){
			this.popUp();
		}
		else{
			this.popDown();
			this.popupIsOpen = false;
		}
	},
	
	/**
	 * Popup the display of the Friends picker.
	 * @param {Object} thisRef optional ref to this object - needed on timeout
	 */
	popUp: function(){
		if(!this.dataLoaded){
			var thisRef = this;
			this._setLoadingMessageDisplay(true);
			if(++this._popupRetries < this.MAX_RETRIES){
				window.setTimeout(function(){
					thisRef.popUp();
				}, 250);
				return;
			}
			else{
				//throw "Timeout loading friend data";
				var msg = "Time loading friends.\nContinue waiting?"
				if(confirm(msg)){
					this._popupRetries = 0;
					this.popUp();
				}
			}
			
		}
		this.drawFriendsPage(this.currentPage);
		if(this.popupWindow){
			this.popupWindow.style.display="block"
			if(this.popupX > 0){
				this.popupWindow.style.left = this.popupX;
				this.popupWindow.style.top = this.popupY;
			}
		}
		this.popupIsOpen = true;
		var searchBox = document.getElementById(this.ElementIDs.searchBox);
		if(searchBox){
			searchBox.focus();
		}
		if(window.event){
			window.event.cancelBubble = true;
		}
	},
	
	/**
	 * Hide the friend picker popup.  Synonymous with close.
	 */
	popDown: function(){
		if(this.popupWindow){
			this.popupWindow.style.display="none"
		}
		this.popupIsOpen = false;
	},
	
	/**
	 * Set the selected friend value.  Must be closure safe
	 * @param {Object} person		The person object or ID string
	 */
	_setSelectedFriend: function(person){
		
		if(typeof(person) === "string"){
			person = this.friendsCatalog.getFriend(person);
		}
		
		this.selectedFriend = person;
		if(this.buildSelectedUI){
			var elem = document.getElementById("__selectedFriendDiv");
			if(elem){
				while(elem.hasChildNodes()){
					elem.removeChild(elem.lastChild);
				}
				elem.appendChild(this._buildSelectedUIDOM(person));
			}
		}
		var selElem = document.getElementById(this.ElementIDs.popTrigger);
		if(selElem){
			selElem.style.display="none";
		}
		this.popDown();
		if(this.friendClickAction){
			if (typeof(this.friendClickAction) == "function") {
				this.friendClickAction(person);
			}
			else if (typeof(this.friendClickAction) == "String") {
				try{
					window.eval(this.friendClickAction+"(" + person + ")");
				}
				catch(ex){}
			}
		}
		
	},
	
	/**
	 * Obtain DOM node containing friend representation
	 * @param {Object} person
	 */
	_getFriendDOM: function(person){
		var makeElem = MyOpenSpace.Widgets.Utility.domElement;
		var styleIt = MyOpenSpace.Widgets.Utility.applyInlineStyle;			
	
		if (person == null || !person.getField) {
			return this._emptyNode;
		}
		
		//embed attributes
		var id = person.getField(opensocial.Person.Field.ID);
		var name = person.getField(opensocial.Person.Field.NAME);
		var cleanName = name;
		if (cleanName) {
			re = /"/g
			cleanName = cleanName.replace(re, "'");
		}
		var keyId = person.getField(opensocial.Person.Field.ID);
		var imgBucket = makeElem("span",
							[
								makeElem("span", 
										this._getFriendThumbnail(person), {style:"width:70px;text-align:left;"}),
								makeElem("span", name)
							],
							{friendid:id});
		

		var stuff = makeElem("div", imgBucket);
		
		styleIt(imgBucket, this.Styles.styleFriendPickImageBlock);
		styleIt(stuff, this.Styles.styleFriendPickBlock);
		styleIt(stuff, {cursor:"pointer"})
		var funcs = new Array();
		var thisRef = this;

		stuff.onclick=function(){
					thisRef._setSelectedFriend(person);
		};
		
		return stuff;
	},
	
	/**
	 * Return a DOM image node with the thumbnail
	 * @param {Object} person
	 */
	_getFriendThumbnail: function(person){
		if (person == null) {
			return this._emptyNode;
		}
		
		var src = person.getField(opensocial.Person.Field.THUMBNAIL_URL);
		if (src == null) 
			return this._emptyNode;
		
		var cleanName = person.getField(opensocial.Person.Field.NAME);
		if (cleanName) {
			re = /"/g
			cleanName = cleanName.replace(re, "'");
		}

		var imgStyle = "height:40px;margin-right:10px;";
		if(this._isIE){
			imgStyle += "width:40px;"
		}
		
		var img = document.createElement("img");
		img.setAttribute("src", src);
		img.setAttribute("alt", "Picture of " + cleanName);
		img.setAttribute("align", "middle");
		img.setAttribute("style", imgStyle)
		img.setAttribute("height", "40");
		if (this._isIE) {
			img.setAttribute("width", "40");
		}
		return img;
	},
	
	/**
	 * Scroll to display a different page
	 * @param {Object} pageNum
	 */
	goToPage: function(pageNum){
		var maxPages = this.pageCount();
		if (pageNum < 1){
			alert('At first page')
			pageNum = 1;
		}
		else if(pageNum > maxPages){
			alert('At last page')
			pageNum = maxPages;
		}			
			
		this.drawFriendsPage(pageNum);
	},
	/**
	 * Trigger a load of the Friend data via the OpenSocial app
	 */
	loadData: function(){
		if(this.dataLoaded){
			this._friendsData = null;
			this.friendMap = new Array();
		}
		this._loadOpenSocialFriends();
	},
	
	/* =======================================
	 * Event handlers
	 * =======================================
	 */
	personSelected: function(personID){
		var person = this.friendMap[personID];
		var name = person.getField(opensocial.Person.Field.NAME);
		alert('You clicked on ' + name);
	},
	
	nextPage: function(){
		this.goToPage(this.currentPage+1);		
	},	
	prevPage: function(){
		this.goToPage(this.currentPage-1);		
	},	
	firstPage: function(){
		this.goToPage(1);
	},	
	lastPage: function(){
		this.goToPage(99);
	},
	
	/**
	 * Initializes the object.
	 * Arguments may be a string of the div id, an element,
	 * or an object literal with options
	 * 
	 * Options:
	 * 		element					-> element or ID of element to draw to
	 * 		friendClickAction		-> callback method for friend click
	 * 		buildSelectedUI			-> true/false to build UI for selected item
	 */
	initialize: function(args){
		var element = null;
		if(!args){ return;}
		if(typeof(args)== 'string'){
			element = args;
		}
		
		element = args.element;
		this.friendClickAction = args.friendClickAction;
		this.buildSelectedUI = args.buildSelectedUI;
		
		if (typeof(element) == 'string') {
			this.DOMElement = document.getElementById(element);
		}
		else {
			this.DOMElement = element;
		}
		this.loadData();
		this._buildDOM();
	}
};

function pickedOne(person){
	//alert('picked ' + person.getField(opensocial.Person.Field.NAME));
	document.getElementById('slectId').value=person.getId();
}

/*
============================================================================================
       END MyOpenSpace.Widgets include.

       Please note that this will be moved to a standard library and
       you should utilize that library once it is announced.
============================================================================================
*/






var osContainer = opensocial.Container.get();

	
function resize(height){
	opensocial.Container.get().resizePanel(height);
}

function sendMessage(personF,msg,appID){
	var elem;
	var content, subject;
	// alert(personF);
	arrF= new Array();
	var req = opensocial.newDataRequest();
	req.add(req.newFetchPeopleRequest ('VIEWER_FRIENDS'), 'viewerFriends');
	req.send(function(dataResponse){
	var viewerFriends = dataResponse.get('viewerFriends').getData();
	//alert(viewerFriends);
	viewerFriends.each(function(person) {
	var key = person.getField(opensocial.Person.Field.ID)
		if (key) {
			key = key.toString();
		}
		else {
			alert('no key');
			return;
		}
		
		if (!arrF[key]) {
			arrF[key] = person;
			//alert(arrF[key]);
		}
		});
	
	
		postType = 'SEND_MESSAGE';

		subject=" Check out my animated Family Tree ";
		content="<br>&nbsp;&nbsp;View my tree and display your own animated family tree.<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='" + htree.INST_URL + "'> Click here to get started ! </a>";
	    content+="<br><a href='" + htree.INST_URL + "'><img border=0 src=\"http://www.hellotree.com/resources/images/message_splash.jpg\"></a>";
			
		
		var recipientPerson = null;

	//recipientPerson = window.friendPicker.selectedFriend;
	recipientPerson = arrF[personF];
	os_token = MyOpenSpace.MySpaceContainer.OSToken;
	
	var message;
	message = opensocial.newMessage(content);
	message.setField(opensocial.Message.Field.TITLE, subject);
	message.setField(opensocial.Message.Field.TYPE, postType);
		
	if(postType == "SEND_MESSAGE" || postType == "COMMENTS"){
		if(!recipientPerson){
			alert('please select a recipient');
			return;
		}
	}



	if(osContainer.postTo){
		//make sure the desired target is currently enabled
		if(!isPostToTargetLive(postType)){
			alert('Target ' + postType + ' is currently disabled');
		}
		else{
			osContainer.postTo(os_token, message, recipientPerson);		
		}
	}
	else{
		alert("This version of MySpace OpenSocial does not support PostTo")
	}
});
}


function getFriendObject(){
	
	recipientPerson = window.friendPicker.selectedFriend;
	var profile_nameO = recipientPerson.getField(opensocial.Person.Field.NAME);
var profile_pic = recipientPerson.getField(opensocial.Person.Field.THUMBNAIL_URL);
var profile_name = recipientPerson.getDisplayName();
var profile_id=recipientPerson.getId();
			alert(profile_name);
			alert(profile_id);
			
}


function isPostToTargetLive(target){
	var supported = osContainer.getMySpaceEnvironment().getSupportedPostToTargets();
	var isSupported = false;
	for(var i = 0; i < supported.length; i++){
		if(supported[i] === target){
			isSupported = true;
			break;
		}
	}
	return isSupported;
}


/**
 * Obtains the currently selected post type
 */
function getSelectedPostType(){
	var elem = document.forms[0].elements['profileTarget'];
	var val;
	if(elem){
		for(var i=0; i < elem.length; i++){
			if(elem[i].checked){
				val = elem[i].value;
				break;
			}
		}
	}	
	return val;
}



function loadFriendPicker(){
	window.friendPicker = new MyOpenSpace.Widgets.FriendPicker(
		{
			element: "picker",
			friendClickAction: pickedOne,
			buildSelectedUI: true
		});
}

function setPickerEnabled(enabled){
	var elem = document.getElementById('fpOverlay');
	if(elem){
		var show = "block";
		if(enabled) show = "none";
		elem.style.display=show;
	}
}

var introShown = false;
function toggleIntro(){
	var elem = document.getElementById('intro');
	if(!elem) return;
	if(introShown){
		elem.style.display="none";
	}
	else{
		elem.style.display="block";
	}
	introShown = !introShown;
}
/////*****/////
function postToContainer(personF){
var val;
val=document.getElementById('hdnInvite').value;

if(val=='')
{
val2=personF+",";
document.getElementById(personF).style.backgroundColor="#CAC3C3";
}
else
{	
	var matchp = val.search(personF);
	if(matchp==-1)
	{		
		val2=val+personF+",";
    document.getElementById(personF).style.backgroundColor="#CAC3C3";		
	}
	else
	{
			val2 = val.replace(personF+",",'');
	document.getElementById(personF).style.backgroundColor="#ffffff";			
	}


}
document.getElementById('hdnInvite').value=val2;
}

////////////////////

function cC(){
   location.href = "#mainFrameTop";
}
function oZ(lQ){
        l.innerHTML = "";

        var bZ = document.createElement("div");
        l.appendChild(bZ);
        bZ.style.textAlign = "center";
        bZ.style.padding = "6px";
        new aJ(bZ, "Send Comments!", iG);

        var gx = document.createElement("div");
        l.appendChild(gx);
        gx.style.textAlign = "center";
        gx.style.padding = "10px";
        var lk = new dI(gx, true);

        var gR = lk.by();
        gR.style.paddingRight = "30px";
        gR.innerHTML = "<span style='color:#3B5998; font-size:12px; font-weight:bold'> [Randomly Select 10 Friends] </span>";
        gR.style.cursor = "pointer";
        aG(gR, "click", oa);

        var ik = lk.bf();
        ik.innerHTML = "<span style='color:#3B5998; font-size:12px; font-weight:bold'> [Clear Selection] </span>";
        ik.style.cursor = "pointer";
        aG(ik, "click", le);        


        var bi = document.createElement("div");
        l.appendChild(bi);
        bi.style.textAlign = "center";
        bi.style.height = "650px";
        bi.style.overflow = "auto";

        bZ = document.createElement("div");
        l.appendChild(bZ);
        bZ.style.textAlign = "center";
        bZ.style.padding = "12px";
        new aJ(bZ, "Send Invites!", iG);

        var dz = document.createElement("table");
        dz.style.borderSpacing = "2px";
        dz.style.border = "none";
        dz.style.marginLeft = "auto";
        dz.style.marginRight = "auto";
        var ii = document.createElement("tbody");
        dz.appendChild(ii);

        var aW = document.createElement("tr");
        ii.appendChild(aW);
        var cD = 0;

        bi.appendChild(dz);

        for (var r = 0; r < lQ.length; r++){
            var lI = lQ[r];

            if(MAIN_DATA.dx(lI.B())){
                continue;
            }

            if(cD >= 5){
                aW = document.createElement("tr");
                ii.appendChild(aW);
                cD = 0;
            }
            aW.appendChild(oI(lI));
            cD += 1;
        }
    }
function g(aM) {
        return (aM != undefined && aM != null);
    }
	function jz()
	{
	}
	
function mx(){
        iV = new Object();
        bC = new Array();
        hd = new Array();
        dH = 0;
		if(!g(OYF.VIEWER_FRIEND_CACHE)){
			//alert('hello');
            OYF.VIEWER_FRIEND_CACHE = new jz();
        }
    }
    
 
		var arrF= null; 
		var kT = null;
		var totalNumOfRequests = 0;
		var currentRequest = 0;
		var  pageMax= 35;
		
    function iG1()
    {	
        totalNumOfRequests = getTotalNumPages(pageMax);        
        currentRequest = 1;   
             
        
        if(totalNumOfRequests >= 1)
        
		    makeRequest();
	}
		
		function makeRequest()
		{
		    var i = currentRequest;	    
		    var startIndex = (i-1)*pageMax;		
		    var params = {};
                 params[opensocial.DataRequest.PeopleRequestFields.MAX] = pageMax;
                 params[opensocial.DataRequest.PeopleRequestFields.FIRST] = startIndex;     
            var req = opensocial.newDataRequest();         
	        req.add(req.newFetchPeopleRequest ('VIEWER_FRIENDS', params), 'viewerFriends');
	        req.send(handleReturnedData);        
	       
		}
		
		function handleReturnedData(dataResponse)
		{		
	                var viewerFriends = dataResponse.get('viewerFriends').getData();               	
	              
	                        viewerFriends.each(function(person) {                        	
	                                var key = person.getField(opensocial.Person.Field.ID); 
	                                  	
                        	
		                                if (key) {
			                                key = key.toString();                        			
		                                }
		                                else {
			                                alert('no key');
			                                return;
		                                }
                                		
		                                if (!arrF[key]) {
			                                arrF[key] = person;				                            	                                                			
		                                }
		                                });
		                        
		                        //make the recursive calls
		                        currentRequest = currentRequest + 1;
		                        
		                         
		                        		                        
		                        if(currentRequest > totalNumOfRequests)
		                        {    
		                           sendInvites();
                                 }
                                 else
                                 {    
                                    makeRequest(currentRequest);
                                 }                                   
                		
		                
		}

function sendInvites()
{
 var ids=document.getElementById('hdnInvite').value;		
	                                mySplitResult=ids.split(',');
		                            var	length = mySplitResult.length;  
		                                    		
                                    for(var r = 0; r < length; r++){
	                                   // alert(mySplitResult[r]);	
    		                            var ab = mySplitResult[r];
                                                     	    
    	                                if(ab != ''){ 
                                	        	       	   
			                                ab = arrF[ab];	
			                                                    			    
			                                if(!YAHOO.lang.isUndefined(ab)){
                            			
			                                kT.push(ab);
			                                }
			                            }			
                                    }
                                    cC();
                                    mz(kT, 0);
}

function iG(){
		
		
		arrF = null;
		arrF =  new Array();  
		
		kT = null;
		kT = new Array();
		
		totalNumOfRequests = 0;
		currentRequest = 0;
		
		iG1();
    }
	
function mz(jD, lS){

        var ab = jD[lS];
        
        var onSentComment = function(aV){
            
            var nd = lS + 1;
			jd1=jD.length;
            if(nd <= jd1-1){
                mz(jD, nd);
            } else {
			
                mx();
            }
        }

        var I;
        I = (Math.random() * 20);
        I = Math.floor(I);
        				
        iB(ab, onSentComment);
    }

	function OYF_appendSourceToken(eG, it, na, ia, qJ, rE){
    var rx = 2;
    var ry = 8;
    var rz = 8;
    var rw = 8;
    var l_len5 = 8;

    var result = eG + "&source=";
    if (it != undefined) {
        result += pad(it, rx);
        if (na != undefined) {
            result += "_" + pad(na, ry);
            if (ia != undefined) {
                result += "_" + pad(ia, rz);
                if (qJ != undefined) {
                    result += "_" + pad(qJ, rw);
                    if (rE != undefined) {
                        result += "_" + pad(rE, l_len5);
                    }
                }
            }
        }
    }
    return result;
}

function pad(str, len) {
  for (var i = 0; i < len && str.length < len; i++) {
    str += ".";
  }

  str = str.substr(0, len);
  return str;
}
function iB(aF,bI){
    
   var postType = 'SEND_MESSAGE';
 
 //this block is only one actaully used
	var	subject=" Check out my animated Family Tree ";
	var content="<br>&nbsp;&nbsp;View my tree and display your own family tree.<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='" + htree.INST_URL + "'> Click here to get started ! </a>";
		   content+="<br><a href='" + htree.INST_URL + "'><img border=0 src=\"http://www.hellotree.com/resources/images/message_splash.jpg\"></a>";
			
	//var recipientPerson = null;
    var T;
	T = opensocial.newMessage(content);
	T.setField(opensocial.Message.Field.TITLE, subject);
	T.setField(opensocial.Message.Field.TYPE, postType);


    V_LIBRARY_OS_CONTAINER.postTo(MS_OS_TOKEN, T, aF, bI);
}


function el(au){
   content="<br>&nbsp;&nbsp;View my tree and display your own family tree.<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='" + htree.INST_URL + "'> Click here to get started ! </a>";
   content+="<br><a href='" + htree.INST_URL + "'><img border=0 src=\"http://www.hellotree.com/resources/images/message_splash.jpg\"></a>";
			
    return content;
}

////////////////////



/////*****/////
