
gadgets.util.registerOnLoadHandler(init); // once loaded, call init()


var os;
var dataReqObj;

var requestedPage = 'index.php'; // default to index
var logEvents = [];

var ownerId = 0;
var viewerId = 0;
var ownerData = null;
var viewerData = null;

var usersData = [];
var usersFriendData = [];
var usersFriendIds = [];
var appUsersFriendIds = [];
var strangerData = new Hash();
var strangerCache = [];
var max_stranger_requests = 100;
var stranger_requests_made = 0;
var fields = [];

var friends_to_invite = [];
var last_invited_friend_id = null;

var friend_block_offset = 0;
var friend_batch_size = 100;
var app_friend_block_offset = 0;

var nameElements = new Hash();
var photoElements = new Hash();
var current_domain;

var page_load_error_count = 0;

var init_called = false;

var invite_message = null;
var g_pending_notifs = [];
var g_pending_newsfeeds = [];
var g_notif_sent = false;
var g_newsfeed_sent = false;

var loading_spinner_html = '<div id="spinner" style="position:absolute;top:200px; left:350px; text-align: center; z-index:9999; visibility:hidden;"><img src="http://fhkfauaa.joyent.us/images/loading.gif"><br /><br />Please wait as we load the best game ever. EVER.</div>';
//'<div id="spinner"><center>Please wait as we load the best game ever. EVER.<br><img style="border: none;" src="http://dbe40282.fb.joyent.us/vehicles/images/design/spinner.gif"/></center></div>';

if (window.open_social_version === undefined)
{
    if (window.app_title === undefined)
	    var open_social_version = 8;
    else
        var open_social_version = 8;
}
function extract_url_parameter( name )
{
    name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");  
    var regexS = "[\\?&]"+name+"=([^&]*)";  
    var regex = new RegExp( regexS );  
    var results = regex.exec( window.location.href );  
    if( results == null )    
        return "";  
    else    
        return results[1];
}

// main entry -- just ready our os stuff for use as needed
function init() {

    if (init_called)
        return;
    
    toggleSpinner(true);
    init_called = true;
	//console.log("open_social_version: %s", open_social_version);
	
    //pageContent = document.getElementById('page_content');
    //pageContent.innerHTML = loading_spinner_html;

	window.countdownTimers = new Array();

    current_domain = opensocial.getEnvironment().getDomain();

    var url_params_string = null;
    
    if (current_domain == "myspace.com")
       url_params_string = 'p';
    else if (current_domain == "hi5.com")
    {
        url_params_string = 'view-params';
//        open_social_version = 7;
	}
	// see if we've specified a url in 
	var decodedURIParam = decodeURIComponent(extract_url_parameter(url_params_string));
		
    if (decodedURIParam) {
		var paramsJSON = eval("("+ decodedURIParam +")"); // eval to json object
        if (paramsJSON != null) {
			if (typeof paramsJSON.requestedPage != 'undefined') {
   				requestedPage = paramsJSON.requestedPage;
			}
			if (typeof paramsJSON.logEvent != 'undefined') {
				logEvents.push(paramsJSON.logEvent);
			}
		}
   	}
    
	os = opensocial.Container.get();
	dataReqObj = os.newDataRequest();
	
    //if (current_domain == "myspace.com")
//        MyOpenSpace.DefaultPageSize = 3000;
        
    // note that on hi5, we can query 500 friends at a time.
    if(current_domain == "hi5.com")
        friend_batch_size = 500;
  
    // create a list of Person fields to fetch,
	friend_block_offset = 0;
    if (open_social_version == 8)
    {
	    fields = 	[
		            opensocial.Person.Field.HAS_APP,
		            opensocial.Person.Field.ID,
		            opensocial.Person.Field.NAME,
		            opensocial.Person.Field.PROFILE_URL,
		            opensocial.Person.Field.THUMBNAIL_URL
					];
	     
		var params = {};
		var idspec = {};
		
		//// we can specify add'l details if needed later, but prof_details must be set for this call to work.  
		var optParams = {};
//		optParams[opensocial.DataRequest.PeopleRequestFields.PROFILE_DETAILS] = fields;

//		params[opensocial.IdSpec.Field.USER_ID] = opensocial.IdSpec.PersonId.OWNER;
		//params[opensocial.IdSpec.Field.NETWORK_DISTANCE] = 0;
		//idspec = opensocial.newIdSpec(params);
   		dataReqObj.add(dataReqObj.newFetchPersonRequest(opensocial.IdSpec.PersonId.OWNER, optParams), 'owner');

//		params[opensocial.IdSpec.Field.USER_ID] = opensocial.IdSpec.PersonId.VIEWER;
		//params[opensocial.IdSpec.Field.NETWORK_DISTANCE] = 0;
//		idspec = opensocial.newIdSpec(params);
   		dataReqObj.add(dataReqObj.newFetchPersonRequest(opensocial.IdSpec.PersonId.VIEWER, optParams), 'viewer');
   		
		// will need to loop through these to accommodate > 200 friends
//		params[opensocial.IdSpec.Field.USER_ID] = opensocial.IdSpec.PersonId.VIEWER;
//		params[opensocial.IdSpec.Field.NETWORK_DISTANCE] = 1;

		request_friend_data (dataReqObj, true, true);		
	}
	else
	{
		var optParams = {};
		optParams[opensocial.DataRequest.PeopleRequestFields.PROFILE_DETAILS] = [];

		// batch together all of our various data requests
   		dataReqObj.add(dataReqObj.newFetchPersonRequest('OWNER', optParams), 'owner');
   		dataReqObj.add(dataReqObj.newFetchPersonRequest('VIEWER', optParams), 'viewer');

		request_friend_data (dataReqObj, true, true);		
	}
	
	// request the google analytics script so that it's always accessible here --
	// this way, we avoid an unncessary http request on every requestPage call
	var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
	var head = document.getElementsByTagName('head')[0];
	var scriptEl = document.createElement('script');
	scriptEl.type = "text/javascript";
	scriptEl.src = unescape(gaJsHost + "google-analytics.com/ga.js");
	head.appendChild(scriptEl);
}

function request_friend_data(req_obj, req_friends, req_app_friends)
{
    if (open_social_version == 8 && current_domain == 'myspace.com')
	    var first_offset = friend_block_offset * friend_batch_size + 1;
    else	
	    var first_offset = friend_block_offset * friend_batch_size;
                                               
    if (open_social_version == 8 && current_domain == 'myspace.com')
	    var first_app_offset = app_friend_block_offset * friend_batch_size + 1;
    else	
	    var first_app_offset = app_friend_block_offset * friend_batch_size;
	    
    // create a list of Person fields to fetch,
    if (open_social_version == 8)
    {
		if (current_domain == "hi5.com")
		{
			if (req_friends)
			{
			    var viewerFriendsParams = {};
				viewerFriendsParams[opensocial.DataRequest.PeopleRequestFields.FIRST] = first_offset;
  				viewerFriendsParams[opensocial.DataRequest.PeopleRequestFields.MAX] = friend_batch_size;
				viewerFriendsParams[opensocial.DataRequest.PeopleRequestFields.PROFILE_DETAILS] = fields;
				req_obj.add(req_obj.newFetchPeopleRequest(opensocial.DataRequest.Group.VIEWER_FRIENDS, viewerFriendsParams), 'viewer_friends');
			}
			
			// because hi5 doesn't support profile_details in 0.8 yet, we have to get the app friends separately.  Grrr.
			if (req_app_friends)
			{
			    var appFriendParams = {}; 
			    appFriendParams[opensocial.DataRequest.PeopleRequestFields.FIRST] = first_app_offset; 
			    appFriendParams[opensocial.DataRequest.PeopleRequestFields.MAX] = friend_batch_size; 
			    //appFriends[opensocial.DataRequest.PeopleRequestFields.SORT_ORDER] = opensocial.DataRequest.SortOrder.NAME; 
			    appFriendParams[opensocial.DataRequest.PeopleRequestFields.FILTER] = opensocial.DataRequest.FilterType.HAS_APP; 
				req_obj.add(req_obj.newFetchPeopleRequest(opensocial.DataRequest.Group.VIEWER_FRIENDS, appFriendParams), 'viewer_app_friends');
			}
		}
		else
		{
			var params = {}
			params[opensocial.IdSpec.Field.USER_ID] = opensocial.IdSpec.PersonId.VIEWER;
			params[opensocial.IdSpec.Field.NETWORK_DISTANCE] = 1;
			var idspec = opensocial.newIdSpec(params);

			if (req_friends)
			{			
			    var viewerFriendsParams = {};
			    viewerFriendsParams[opensocial.DataRequest.PeopleRequestFields.FIRST] = first_offset;
			    viewerFriendsParams[opensocial.DataRequest.PeopleRequestFields.MAX] = friend_batch_size;
	//		    viewerFriendsParams[opensocial.DataRequest.PeopleRequestFields.PROFILE_DETAILS] = fields;
			    var viewerFriendsReq = req_obj.newFetchPeopleRequest(idspec, viewerFriendsParams);
			    req_obj.add(viewerFriendsReq, 'viewer_friends');
			}
			
			// because myspace doesn't support profile_details in 0.8 yet, we have to get the app friends separately.  Grrr.
			if (req_app_friends)
			{
			    var appFriendParams = {}; 
			    appFriendParams[opensocial.DataRequest.PeopleRequestFields.FIRST] = first_app_offset; 
			    appFriendParams[opensocial.DataRequest.PeopleRequestFields.MAX] = friend_batch_size; 
			    //appFriends[opensocial.DataRequest.PeopleRequestFields.SORT_ORDER] = opensocial.DataRequest.SortOrder.NAME; 
			    appFriendParams[opensocial.DataRequest.PeopleRequestFields.FILTER] = opensocial.DataRequest.FilterType.HAS_APP; 
				req_obj.add(req_obj.newFetchPeopleRequest(idspec, appFriendParams), 'viewer_app_friends');
			}
		    
		}	    
	    // increment so that the next request gets the next batch of users
	    friend_block_offset++;
	    app_friend_block_offset++;
	}
	else
	{
		if (req_friends)
		{
		    var viewerFriendsParams = {};
		    viewerFriendsParams[opensocial.DataRequest.PeopleRequestFields.FIRST] = first_offset;
		    viewerFriendsParams[opensocial.DataRequest.PeopleRequestFields.MAX] = friend_batch_size;
		    viewerFriendsParams[opensocial.DataRequest.PeopleRequestFields.PROFILE_DETAILS] = [];
		    var viewerFriendsReq = req_obj.newFetchPeopleRequest(opensocial.DataRequest.Group.VIEWER_FRIENDS, viewerFriendsParams);
		}
		
		if (req_app_friends)
		{
		    var appFriendParams = {}; 
		    appFriendParams[opensocial.DataRequest.PeopleRequestFields.FIRST] = first_app_offset; 
		    appFriendParams[opensocial.DataRequest.PeopleRequestFields.MAX] = friend_batch_size; 
		    //appFriends[opensocial.DataRequest.PeopleRequestFields.SORT_ORDER] = opensocial.DataRequest.SortOrder.NAME; 
		    appFriendParams[opensocial.DataRequest.PeopleRequestFields.FILTER] = opensocial.DataRequest.FilterType.HAS_APP; 
		}
		
	    // increment so that the next request gets the next batch of users
	    friend_block_offset++;
	    app_friend_block_offset++;
	    
	    req_obj.add(viewerFriendsReq, 'viewer_friends');
	    req_obj.add(req_obj.newFetchPeopleRequest(opensocial.DataRequest.Group.VIEWER_FRIENDS, appFriendParams), 'viewer_app_friends');
	}
    req_obj.send(processFriends);
}
	                       
function processFriends(dataResponse) {	
	
	if (open_social_version == 8)
	{
		var response;
		var req_friends = false;
		var req_app_friends = false;
		
		if (!dataResponse) {
			// don't do anything.  The request page at end of function will trigger.
		} else {
	        if (friend_block_offset == 1)
	        {
	        	response = dataResponse.get('owner');
	        	if (response && !response.hadError () && ownerId == 0)
	        	{
	            	ownerData = response.getData();
					ownerId = convert_idv8_to_idv7(ownerData.getField(opensocial.Person.Field.ID));
					usersData.push(ownerData);
				}
				
	            response = dataResponse.get('viewer');
	        	if (response && !response.hadError () && viewerId == 0)
	        	{
	        		viewerData = response.getData();
		            viewerId = convert_idv8_to_idv7(viewerData.getField(opensocial.Person.Field.ID));
				}
	        }

            if (dataResponse.hadError() && (current_domain == "myspace.com")) 
            {
                var data = dataResponse.get('viewer_friends');
                if (!data) {
                    requestPage(appUrl + requestedPage); // request it anyway.    
                } else if (data.getErrorCode() == opensocial.ResponseItem.Error.UNAUTHORIZED) {
                    requestPage('add_app.php'); // an upsell page for non-users
                    return;
                }
            }
	    
			//usersFriendIds.push(ownerData.getField(opensocial.Person.Field.ID));

            response = dataResponse.get('viewer_friends');
			var friendsCollection = null;
	        if (response && !response.hadError ())
	        {
				friendsCollection = response.getData();
				
		        friendsCollection.each(
		            function(friendData) 
		            {
		                var id = convert_idv8_to_idv7(friendData.getField(opensocial.Person.Field.ID, 10));
						if (usersFriendIds.indexOf(id) == -1)
						{
			                usersData.push(friendData);
			                
			                usersFriendIds.push(id); 
						}			                
			            // check if this is a fiend with the app installed.  If so, also push him into the app friends list
						if (appUsersFriendIds.indexOf(id) == -1)
						{
				            if (friendData.getField(opensocial.Person.Field.HAS_APP) == true)
				            {
                				appUsersFriendIds.push (id);
							}
						}
		                //users_friend_data.push(current_friend_data);
		            }
		        )
				if (current_domain == "myspace.com")
				{
					if (friendsCollection != null && (friendsCollection.size () > 0 && friend_block_offset < 100))
						req_friends = true;
				}
				else
				{
					if (friendsCollection != null && (usersFriendIds.length < friendsCollection.getTotalSize() && friend_block_offset < 100))
						req_friends = true;
				}
			}
			
            response = dataResponse.get('viewer_app_friends');
            if (response)
            {
		        var appFriendsCollection = response.getData();
				if (appFriendsCollection)
				{
	            	appFriendsCollection.each(
			        	function(friendData) 
			            {
				        	var id = convert_idv8_to_idv7(friendData.getField(opensocial.Person.Field.ID, 10));
							if (appUsersFriendIds.indexOf(id) == -1)
							{
									appUsersFriendIds.push(id); 
							}
						}
			        )
				}
				if (current_domain == "myspace.com")
				{
					if (appFriendsCollection != null && (appFriendsCollection.size () > 0 && app_friend_block_offset < 100))
						req_app_friends = true;
				}
				else
				{
					if (appFriendsCollection != null && (appFriendsCollection.length < appFriendsCollection.getTotalSize() && app_friend_block_offset < 100))
						req_app_friends = true;
				}
			}			
			if (req_friends || req_app_friends)
			{
			   	dataReqObj = os.newDataRequest();
		        request_friend_data(dataReqObj, req_friends, req_app_friends);
		        return;
		    }
		}
		// now display my requested page
		requestPage(appUrl + requestedPage);
	}
	else
	{
		if (dataResponse.hadError()) {
   	 		var data = dataResponse.get('viewer_friends');
			if (!data) {
				requestPage(appUrl + requestedPage); // request it anyway.	
			} else if (data.getErrorCode() == opensocial.ResponseItem.Error.UNAUTHORIZED) {
				requestPage('add_app.php'); // an upsell page for non-users
                return;
			}
		} else {
	    
	    
	        if (friend_block_offset == 1)
	        {
	            ownerData = dataResponse.get('owner').getData();
	            viewerData = dataResponse.get('viewer').getData();
	            ownerId = ownerData.getField(opensocial.Person.Field.ID);
	            viewerId = viewerData.getField(opensocial.Person.Field.ID);
	            
	            usersData.push(ownerData);
	        }

	    
			//usersFriendIds.push(ownerData.getField(opensocial.Person.Field.ID));

	 		var friendsCollection = dataResponse.get('viewer_friends').getData();
	        //user_friend_ids = [];


	        friendsCollection.each(
	            function(friendData) 
	            {
	                usersData.push(friendData);
	                usersFriendIds.push(friendData.getField(opensocial.Person.Field.ID, 10)); 
	                //users_friend_data.push(current_friend_data);
	            }
	        );
	        
	        var appFriendsCollection = dataResponse.get('viewer_app_friends').getData();

	        if (appUsersFriendIds.length < appFriendsCollection.getTotalSize())
	        {
	            appFriendsCollection.each(
	                function(friendData) 
	                {
	                    appUsersFriendIds.push(friendData.getField(opensocial.Person.Field.ID, 10)); 
	                }
	            );       
	        }
	        
	        if (usersData.length < friendsCollection.getTotalSize() && friend_block_offset < 100)
	        {
	            request_friend_data(dataReqObj, true, true);
	            return;
	        }
	                
			// now display my requested page
			requestPage(appUrl + requestedPage);
		}
	}
}

// strips out myspace: from id string, if it exists.
function convert_idv8_to_idv7 (idString)
{
	var i = idString.indexOf (":");
	if (i < 0)
		return idString;
	else
		return idString.slice(i + 1);
}

function requestStrangerData ()
{
	return;
    dataReqObj = os.newDataRequest();
	var optParams = {};
	optParams[opensocial.DataRequest.PeopleRequestFields.PROFILE_DETAILS] = [];
	stranger_requests_made = 0;
	
	while (strangerCache.length > 0 && stranger_requests_made < max_stranger_requests)	// don't allow more than 100 data requests at a time.
	{	
   		dataReqObj.add(dataReqObj.newFetchPersonRequest(strangerCache.pop (), optParams), 'stranger'+stranger_requests_made);
   		stranger_requests_made++;
	}
    dataReqObj.send(processStrangers);
}

function processStrangers(dataResponse) {	
	
	if (dataResponse.hadError()) {
	} else {
		for (var i = 0; i < stranger_requests_made; i++)
		{
            var sData = dataResponse.get('stranger'+i).getData();
            if (!sData)
            	continue;
            	
            // got some stranger data.  Add it to the hash for all stranger data.
            strangerData.add (convert_idv8_to_idv7(sData.getField(opensocial.Person.Field.ID)), sData);
        }

		if (strangerCache.length > 0)
		{
			// there are more strangers to process.  Go ahead and process them.
			requestStrangerData ();
			return;
		}
                
		// now update the elements of the page relevant to stranger ids.
		setNameElements ();
//		requestPage(appUrl + requestedPage);
	}
}

function goToCanvas(page, ownerId) {
    var surfaces = opensocial.getEnvironment().getSupportedSurfaces();
    var params = { "page" : page, "owner_id" : ownerId};

    opensocial.requestNavigateTo(surfaces.canvas, params);
}

function goToInvite(custom_msg) 
{
	var msg = custom_msg;
	if (custom_msg == null)
		msg = 'Level up by getting your friends to join!';
	var params = {};
	
	// This is an odd bug - we can't pass in params to this message, otherwise it breaks the invite control that 
	// hi5 pops up.
//	var msgObj = opensocial.newMessage(msg, params);
	var msgObj = opensocial.newMessage(msg);
	opensocial.requestShareApp(opensocial.DataRequest.Group.VIEWER_FRIENDS, msgObj); /// hi5 ignores callback here. 
}

function toggleSpinner(force) {
	var spinner = document.getElementById('loading');
	if (!spinner) { return false; }
	var setToVisibility = "hidden";
	if (typeof force == 'undefined') {
		// no force passed, just toggle to show if already hidden
		if (spinner.style.visibility == "hidden") {
			setToVisibility = "visible";
		}
	} else {
		// force to the specified position
		setToVisibility = ((force === true) ? "visible" : "hidden");
	}
	spinner.style.visibility = setToVisibility;
}

function reloadLastRequest() {
    if (lastRequestForRelaod) {
        requestPage(lastRequestForRelaod['full_url'], lastRequestForRelaod['name'], lastRequestForRelaod['postdata']);
    }

}

function requestPage(fullURL, name, postdata) {
    lastRequestForRelaod = Array();
    lastRequestForRelaod['full_url'] = fullURL;
    lastRequestForRelaod['name'] = name;
    lastRequestForRelaod['postdata'] = postdata;
    

	if (typeof window.countdownTimers != 'undefined' && window.countdownTimers.length > 0) {
		for (var i=0; i < window.countdownTimers.length; i++) {
			clearInterval(window.countdownTimers[i]);
		};
	}
	
	toggleSpinner(true);
        	
	// bad call -- fail silently
	if (fullURL == null) {
		toggleSpinner();
		return false; 
	} else if (fullURL.substr(0,4).toLowerCase() != 'http') {
		fullURL = appUrl + fullURL;
	}
		
	requestedPage = fullURL.split('/').pop();
	
	// grab our requested page!
	params = {};
	params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.POST;
	params[gadgets.io.RequestParameters.AUTHORIZATION] = gadgets.io.AuthorizationType.SIGNED; 
	params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.JSON;
	
	// create the list of user friend ids -- remove owner first
	var friendsOnlyIds = usersFriendIds; //.slice(1);
	usersFriendIdList = friendsOnlyIds.join(",");

	if (postdata == null) {
		var postdata = {};

		if(name != null) {
			postdata['name'] = name;
		}
        
	}
	
	if (friendsOnlyIds.length > 0)
    	postdata['friend_ids'] = usersFriendIdList;
    
    if (appUsersFriendIds.length > 0)
    	postdata['app_friend_ids'] = appUsersFriendIds.join(",");
    
    postdata['open_social_version'] = open_social_version+'';
	for (var i=0; i < logEvents.length; i++) {
		for (var idx in logEvents[i]) {
			postdata[idx] = logEvents[i][idx];
		}
	}
	logEvents = []; // reset
    // console.log("app friends: %s", appUsersFriendIds.join(","));
                                                                       
    params[gadgets.io.RequestParameters.POST_DATA] = gadgets.io.encodeValues(postdata);

	gadgets.io.makeRequest(fullURL, displayPage, params);
}


//// expect json text 
function displayPage(data) {
		
	var raw = data.text;
	var json = eval("("+ raw +")");  //// now create an object for me to parse
	
	if (!json)
	{
		// increment the error count
		page_load_error_count++;

		// if we've had more than 5 errors, go ahead and give up
		if (page_load_error_count >= 5 && requestedPage != 'index.php') 
			requestedPage = 'index.php';

		// request the page again
		requestPage(requestedPage);
		return;
	}

	// no errors, so set the load error count to 0
	page_load_error_count = 0;
	
	// debug info?
	if (json.debug_echo.length && typeof console != 'undefined') {
		for (var i=0; i < json.debug_echo.length; i++) {
			console.debug(json.debug_echo[i]);
		};
	}

    // if we've been given a newAppUrl, then update our appUrl parameter
    // this is how we can move to a new server without waiting for changes in a containter
    if (json.newAppUrl && appUrl != json.newAppUrl) {
        appUrl = json.newAppUrl;
        requestPage(requestedPage);
        return true;
    }

    
	// first see if we have any feed/notifications to handle
	if (json.notification_array.length > 0) {
		for (var i = json.notification_array.length - 1; i >= 0; i--){
			sendNotification(json.notification_array[i]);
		};
	}	
	if (json.newsfeed_array.length > 0) {
		for (var i = json.newsfeed_array.length - 1; i >= 0; i--){
			publishFeed(json.newsfeed_array[i]);
		};
	}
	// dynamically add external scripts
	if (json.script_array.length > 0) {
		var head = document.getElementsByTagName('head')[0];
		for (var i=0; i < json.script_array.length; i++) {
			var scriptEl = document.createElement('script');
			scriptEl.type = "text/javascript";
			scriptEl.src = json.script_array[i];
			head.appendChild(scriptEl);
		};
	}
	if (typeof json.top_redirect != "undefined" && json.top_redirect) {
		top.location = json.top_redirect;
		return;
	}
	if (json.redirect) {
		requestPage(json.redirect);
		return true;
	}
	if (json.navTo){
		switch (json.navTo) {
			case "invite":
				goToInvite();
				break;
			case "canvas":
				goToCanvas();
				break;
			default:
				// ignore
				break;
		}
		return true;
	}
	if (typeof json.combat_return != 'undefined') {
		finishRace(json.combat_return);
		return true;
	}
	
		
	pageContent = document.getElementById('page_content');
	pageContent.innerHTML = json.page_content;

	if (json.show_popup)
	{
		showNotif ();
	}
		
	
    var elements_array = pageContent.getElementsByTagName('script');
    if (elements_array != null)
    {
	    for(var i = 0; i < elements_array.length; i++) {
	    	var cur_element = elements_array [i];
	    	try {
    			eval(cur_element.innerHTML);   // for each script tag, evaluate its contents
                alert(cur_element.innerHTML);
			}
			catch (err) { showError(err.message + "<br>\n" + cur_element.innerHTML) }
	    }
	}	
	
	// -- adapted from phpied.com --
	// see if we have any style definitions to copy in
	// var styleTags = document.getElementsByTagName('style');
	// if (styleTags.length) {
	// 	var cssNode = document.createElement('style');
	// 	cssNode.setAttribute("type", "text/css");
	// 
	// 	// build the style content
	// 	var styleContent = '';
	// 	for (var i=0; i < styleTags.length; i++) {
	// 		styleContent += styleTags[i].innerHTML;
	// 	};
	// 			
	// 	if (cssNode.styleSheet) {
	// 		// IE only
	// 	    cssNode.styleSheet.cssText = styleContent;
	// 	} else {
	// 	    var styleTextNode = document.createTextNode(styleContent);
	// 	    cssNode.appendChild(styleTextNode);
	// 	}
	// 	var head = document.getElementsByTagName('head')[0];
	// 	head.appendChild(cssNode);	
	// }
	
	setNameElements(pageContent);
	
	gadgets.window.adjustHeight(); 				/// resize our window		

	resetTabs();
	toggleSpinner(false);
}

function setNameElements(divContainer) {
	// reset our cache array
    nameElements = new Hash();
	photoElements = new Hash();

    var span_elements_array = divContainer.getElementsByTagName('span');
    for (i=0; i<span_elements_array.length; i++) {

        var current_span_element = span_elements_array[i];

        if (current_span_element.className.slice(0,5) == 'name_') {
			// we've found a name tag
            var current_user_id = current_span_element.className.slice(5);

            // this user exists.  We will be resolve the tags.
	        if (nameElements.contains(current_user_id)) {
	            var current_span_array = nameElements.retrieveByKey(current_user_id);
	            current_span_array.push(current_span_element)
	            nameElements.add(current_user_id, current_span_array);                
	        }
	        else {
	            var current_span_array = [];
	            current_span_array.push(current_span_element)
	            nameElements.add(current_user_id, current_span_array);
	        }
        }
        if (current_span_element.className.slice(0,6) == 'photo_') {
			// we've found a photo tag
            var current_user_id = current_span_element.className.slice(6);
            if (photoElements.contains(current_user_id)) {
                var current_span_array = photoElements.retrieveByKey(current_user_id);
                current_span_array.push(current_span_element)
                photoElements.add(current_user_id, current_span_array);                
            } else {
                var current_span_array = [];
                current_span_array.push(current_span_element)
                photoElements.add(current_user_id, current_span_array);
            }
		}
    }

    // for every user, check if there are elements we should fill
    for (var j = 0; j < usersData.length; j++) {
        var current_user_data = usersData[j];
        replaceTags (current_user_data, nameElements, photoElements);
	}

	// at this point, if there are any nameElements or photoElements that didn't get unset, these are id's of people who are not friends.
	// go through the cached stranger data and see if they exist there.
    // for every user, check if there are elements we should fill
    strangerData.each (
        function(pair) 
        {
			replaceTags (pair.data, nameElements, photoElements);
        }
	)

	// at this point, any elements left that we haven't replaced have user IDs that aren't friends, and we have not already retrieved their data
	// so at this point we must retrieve the data from open social.
	var keys1 = nameElements.keys ();
	var keys2 = photoElements.keys ();
	strangerCache = keys1.concat (keys2);
	// make sure there are no dupes.
	strangerCache = strangerCache.uniq ();
	
	requestStrangerData ();
	
	// toggleSpinner();  /// we're finished, so hide spinner
}

function replaceTags (current_user_data, nameElements, photoElements)
{
    // the id of the user that owns this profile
    //var owner_id = owner.getField(opensocial.Person.Field.ID);
    var owner_id = convert_idv8_to_idv7(current_user_data.getField(opensocial.Person.Field.ID));

    var arrayOfNameElements = nameElements.retrieveByKey(owner_id);
	var arrayOfPhotoElements = photoElements.retrieveByKey(owner_id);

	var nameElementsLength = 0;
	var photoElementsLength = 0;

    if (arrayOfNameElements != null) {
		nameElementsLength = arrayOfNameElements.length;
	}
    if (arrayOfPhotoElements != null) {
		photoElementsLength = arrayOfPhotoElements.length;
	}

	// unset this array key.  We use this to keep track of owner ids that we don't have a matching user data for it.
	nameElements.remove(owner_id);
	photoElements.remove(owner_id);
	
    for (i=0; i < nameElementsLength; i++) {
          arrayOfNameElements[i].innerHTML = current_user_data.getDisplayName();
    }
    for (i=0; i < photoElementsLength; i++) {
          arrayOfPhotoElements[i].innerHTML = '<img src="'+current_user_data.getField(opensocial.Person.Field.THUMBNAIL_URL)+'" />';
    }
}

/*
# TITLE, BODY, MEDIA_ITEMS, FAVICON_URL, and URL
# USER_ID, APP_ID, and POSTED_TIME are inferred from the request and if set are ignored by hi5
# Priority, although required by the OpenSocial spec, is currently ignored by hi5
# FAVICON_URL
*/
function publishFeed(feedObj) {
	
	if (feedObj.version == 8)
	{
		if (g_newsfeed_sent || g_notif_sent)
		{
			g_pending_newsfeeds.push (feedObj);
			return;
		}
		
		var params = {};
		params[opensocial.Activity.Field.TITLE_ID] = feedObj.title_id;
//		params[opensocial.Activity.Field.TEMPLATE_PARAMS] = params[opensocial.Activity.Field.TEMPLATE_PARAMS] = {"fight_phrase":" beat down on ","target":"6221", "fight_details":"<a href=\"http://profile.myspace.com/Modules/Applications/Pages/Canvas.aspx?appId=104192&appParams={\"requestedPage\":\"index.php\"}\">Zombies</a> drinks your milkshake.", "fight_url":"?appId=104192"}; //feedObj.template_params;
		params[opensocial.Activity.Field.TEMPLATE_PARAMS] = feedObj.template_params;

		var mediaItems = [];
		if (current_domain == "myspace.com")
		{
			// on myspace, just use thumbnail images of actors
			var mediaItem = opensocial.newMediaItem('', "http://api.myspace.com/v1/users/" + ownerId);
			mediaItems.push(mediaItem);
			// if tehre is a target, also have their image.
			var target_id = feedObj.template_params['target'];
			if (target_id != undefined)
			{
				mediaItem = opensocial.newMediaItem('', "http://api.myspace.com/v1/users/" + target_id);
				mediaItems.push(mediaItem);
			}
			
		}
		else
		{
			for (var i=0; i<feedObj.images.length && i < 2; i++) 
			{
				var mediaItem = opensocial.newMediaItem('image/jpeg', feedObj.images[i]["url"]);
				mediaItems.push(mediaItem);
			}
		}
		params[opensocial.Activity.Field.MEDIA_ITEMS] = mediaItems;

		var activity = opensocial.newActivity(params);
		opensocial.requestCreateActivity(activity, opensocial.CreateActivityPriority.HIGH, feed_response);
		g_newsfeed_sent = true;
	}
	else
	{
		var activityParams = {};
		activityParams[opensocial.Activity.Field.TITLE] = prepareText(feedObj.title, feedObj.title_uids);

		var mediaItems = new Array();
		for (var i=0; i<feedObj.images.length; i++) {
			var mediaItem = opensocial.newActivityMediaItem(opensocial.Activity.MediaItem.Type.IMAGE, feedObj.images[i]["url"]);
			if(opensocial.getEnvironment().getDomain() == "hi5.com")
			    mediaItem.setField(hi5.ActivityMediaItemField.LINK, feedObj.images[i]["link"]);
			mediaItems.push(mediaItem);
		}
		if (mediaItems.length > 0)
			activityParams[opensocial.Activity.Field.MEDIA_ITEMS] = mediaItems;

		var activity = opensocial.newActivity(activityParams);
		opensocial.requestCreateActivity(activity, opensocial.CreateActivityPriority.HIGH, feed_response);
	}
}

function feed_response (response_item)
{
	g_newsfeed_sent = false;
	if (g_pending_newsfeeds.length > 0)
	{
		feedObj = g_pending_newsfeeds.shift ();
		publishFeed (feedObj);
	}
	else if (g_pending_notifs.length > 0)
	{
		notif_obj = g_pending_notifs.shift ();
		sendNotification (notif_obj);
	}
}

// @desc 	send notification to specified userids
// @param 	notifObj {
//				array 	recipients_array
//				string 	notif_text
//				array 	text_uids
		
function myspaceSendNotification ( notifObj) {
    var messageParams = {};
	var preparedText = prepareText(notifObj.notif_text, notifObj.text_uids);


    // set up a button to go send the defender to our app
    var url = MyOpenSpace.NotificationButton.UrlTypes.CANVAS;

    var button_text = '';
    if ( notifObj.myspace_button_text ) {
        button_text = notifObj. myspace_button_text;
    } else {
        button_text = "Go to " + app_title;
    }
    
    var button = MyOpenSpace.newNotificationButton( url, button_text, notifObj.myspace_query_args);
    messageParams[MyOpenSpace.Notification.Field.BUTTONS] = [ button ];

    
    // get the message set the message body.
    messageParams[MyOpenSpace.Notification.Field.BODY] = preparedText;
    var message = MyOpenSpace.newNotification(messageParams); 
    
    // added the actor's pic
    var mediaItem = opensocial.newMediaItem('', MyOpenSpace.MediaItemHelper.PROFILE_PICTURE);
    messageParams[MyOpenSpace.Notification.Field.MEDIA_ITEMS] = Array( mediaItem );
    
    
    jQuery.each(notifObj.recipients_array, function() {
            MyOpenSpace.requestCreateNotification(this, message,myspacenotificationHandler);
        });
}
function myspacenotificationHandler(res) {
    notificationHandler(res);
}
function sendNotification(notifObj) 
{
	if (g_newsfeed_sent || g_notif_sent)
	{
		g_pending_notifs.push (notifObj);
		return;
	}
	var messageParams = {};
    
    // NOTE: for myspace, opensocial.Message.Type.NOTIFICATION goes to the users bulletin board - 
    // I'm changing this to opensocial.Message.Type.PUBLIC_MESSAGE, which goes to the viewers wall
	var preparedText = prepareText(notifObj.notif_text, notifObj.text_uids);
    if (current_domain == "myspace.com")
    {
        try {
            myspaceSendNotification(notifObj);
        } catch( e) {
            messageParams[opensocial.Message.Field.TYPE] = opensocial.Message.Type.PUBLIC_MESSAGE;
            var message = opensocial.newMessage(preparedText, messageParams);
            opensocial.requestSendMessage(notifObj.recipients_array [0], message, notificationHandler);            
        }
	}
    else
    {
	    messageParams[opensocial.Message.Field.TYPE] = opensocial.Message.Type.NOTIFICATION;
		var message = opensocial.newMessage(preparedText, messageParams);
		opensocial.requestSendMessage(notifObj.recipients_array, message, notificationHandler);
	}
	g_notif_sent = true;

}

// @desc 	iterates through each text_uid and replaces the next <name> tag with the appropriate name
function prepareText(text, textIds) {
	var preparedText = text;
	preparedText = preparedText.replace(/<owner>/, ownerData.getDisplayName());
	for (var i=0; i<textIds.length; i++) {
		var name = "";
		if (textIds[i] == ownerId) name = ownerData.getDisplayName();
		else if (textIds[i] == viewerId) name = viewerData.getDisplayName();
		else {
			var friendIndex = usersFriendIds.indexOf(textIds[i]);
			name = (friendIndex > -1) ? usersData[friendIndex].getDisplayName() : "someone"; 
		}
		preparedText = preparedText.replace(/<name>/, name);
	}
	return preparedText;
}

function notificationHandler(response) 
{
	g_notif_sent = false;
	if (g_pending_notifs.length > 0)
	{
		notif_obj = g_pending_notifs.shift ();
		sendNotification (notif_obj);
	}
	else if (g_pending_newsfeeds.length > 0)
	{
		feedObj = g_pending_newsfeeds.shift ();
		publishFeed (feedObj);
	}
}

// form handler -- simple wrapper for a post request
function submitForm(form, actionUrl) {
	var els = form.elements;
	var json = getJSONFromData(els);
	return requestPage(actionUrl, null, json);
}

// serializes the data for form elements passed to it, in the form "name=value&"
// note that this doesn't take a form itself, only an array of elements -- 
// i want the flexibility to grab only parts of a form or several forms if needed
function getSerializedData(els) {
	var serialized = '';

	for (var i=0; i<els.length; i++) {
		var current = els[i];
		// first see if we're dealing with a checkbox, select, or radio
		if (current.type === "radio" || current.type === "select" || current.type === "checkbox") {
			serialized += (current.checked) ? (current.name +'='+ current.value + "&") : ''; // if it's not selected, don't include
		}
		// otherwise, include it no matter what
		else {
			serialized += current.name +'='+ current.value + "&";
		}
	}
	return serialized;
}


// takes elements with name value pairs and encodes them into an object
function getJSONFromData(els) {
	var json = new Object();

	for (var i=0; i<els.length; i++) {
		var current = els[i];
		// first see if we're dealing with a checkbox, select, or radio
		if (current.type === "radio" || current.type === "select" || current.type === "checkbox") {
			// only include if selected/checked
			if (current.checked) { json[current.name] = escape(current.value); } 
		}
		// otherwise, include it
		else if (typeof current.name != 'undefined' && current.name != '') {
			json[current.name] = escape(current.value);
		}
	}		
	return json;
}



//// fb animation and such
function eventHandler(e) {
	var firedById = e.target.getId();
	var targetDivId = getTargetDivId(firedById);
	switch (e.type) {
		case 'mouseover':
			return showDiv(targetDivId);
			break;
		case 'mouseout':
			return hideDiv(targetDivId);
			break;
		default:
			return false;
	}	
}

function getTargetDivId(firedBy) {
	var targetDivId = firedBy; // default to who fired it
	switch (firedBy) {
		case 'news_tab': 
			targetDivId = 'news_box';
			break;
	}
	return targetDivId;
}

function showNotif() 
{
	return showDiv('notification_box'); 
}
function hideNotif() { return hideDiv('notification_box'); }

// fbanimate wrapper fns
function showDiv(divName) {
	var obj = document.getElementById(divName);
	Animation(obj).to('opacity', 0).duration(0).show().to('opacity', 0.95).duration(500).go();
	return false;
}
function hideDiv(divName) {
	var obj = document.getElementById(divName);
	Animation(obj).to('opacity', 0).duration(500).hide().go();
	return false;
}

// when the user clicks on a picture to select someone, this function is called.
function toggle_invite_status(selected_element, force_value) {

	var selected_user_id = selected_element.getAttribute('user_id');

	var include_user = true;
	if (typeof force_value !== 'undefined') {
		include_user = force_value;
	} else {
		include_user = selected_element.getAttribute('invite') == 0;
	}

	if (include_user) {
		selected_element.setAttribute('invite', 1);

		friends_to_invite.push(selected_user_id);
		selected_element.style.background = '#B05031';
	}else{
		// here the user is deselecting the user
		var temp_friends_array = [];

		// traverse the original array and exclude the user they clicked on
		for (i = 0; i < friends_to_invite.length; i++){
			if (friends_to_invite[i] == selected_user_id)
				continue;
			temp_friends_array.push(friends_to_invite[i]);
		}
		friends_to_invite = temp_friends_array;

    	selected_element.setAttribute('invite', 0);
		selected_element.style.background = '#343434';
	}
}

var all_selected = false;
// select all elements; toggle their invite status
function toggle_select_all() {
	
	all_selected = !all_selected;
	
	$('.potential_invitee').each(function(i,el) { toggle_invite_status(el, all_selected) });
	var currentText = $('#select_all').html();
	var newText = '';
	if (currentText == 'unselect all') {
		newText = 'include all your friends!';
	} else {
		newText = 'unselect all';
	}
	$('#select_all').html(newText);
}


// for inviting more than one friend, this accomplishes that
function invite_group(group_to_invite, new_invite_message)
{
    friends_to_invite = group_to_invite;
    process_invites(new_invite_message);
}

// when the user clicks the button "do invites, this should get called"
function process_invites(new_invite_message){

	// if(friends_to_invite.length == 0){
	// 	alert('you must select at least one friend!');
	// 	return;
	// }

	last_invited_friend_id = friends_to_invite.pop();
    
    if (new_invite_message != null)
        invite_message = new_invite_message;
    
    // if we never get an invite message, use the default.
    if (invite_message == null)
	    invite_message = "Think you've got what it takes? Join me on [app] if you think you can handle it :)";
        
	opensocial.requestShareApp(last_invited_friend_id, opensocial.newMessage(invite_message), invite_callback);
}

function invite_callback(response)
{
	// if we had a successful invite call, notify the url
	if (response.hadError() == false && response.getData() == 1)
	{		
		// notify the save invites page!
		params = {};
		params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.POST;
		params[gadgets.io.RequestParameters.AUTHORIZATION] = gadgets.io.AuthorizationType.SIGNED; 
		params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.JSON;
		
		// create the list of user friend ids
	    usersFriendIdList = usersFriendIds.join(",");

	    var postdata = {'friend_ids' : usersFriendIdList, 'sent_ids' : last_invited_friend_id};
	    params[gadgets.io.RequestParameters.POST_DATA] = gadgets.io.encodeValues(postdata);

		var fullURL = appUrl + 'save-invites.php';

		gadgets.io.makeRequest(fullURL, function(){}, params);
	}
	// if we have more invites, do them!
	if (friends_to_invite.length > 0){
		process_invites();
	} else {
		if (typeof(nextPage) == 'undefined' || nextPage == null)
			nextPage = 'index.php?invites=1';
        requestPage(nextPage);
	}
}

function registerTimer(timerFn, frequency) {
	if (frequency == null)
		frequency = 1000;
	var index = window.countdownTimers.length;
	window.countdownTimers[index] = setInterval(timerFn, frequency);
	return window.countdownTimers[index];
}

// for the store

var currentTabs = [];
currentTabs['sell'] = 'slot_1';
currentTabs['buy'] = 'slot_1';
currentTabs['equip'] = 'slot_1';

function resetTabs() {
	currentTabs['sell'] = 'slot_1';
	currentTabs['buy'] = 'slot_1';
	currentTabs['equip'] = 'slot_1';	
}

function selectTab(tabName, type) {
	if (currentTabs[type] == tabName) {
		return false;
	}
	if (currentTabs[type]) {
		toggleTab(currentTabs[type], type);
	}
	toggleTab(tabName, type);
	currentTabs[type] = tabName;
	return false;
}
function toggleTab(divName, type) {
	// var tabContent = document.getElementById(type+'_section_'+divName);
	// var tabLabel = document.getElementById(type+'_tab_'+divName);
	var tabContent = $('#'+type+'_section_'+divName);
	var tabLabel = $('#'+type+'_tab_'+divName);
	
	var targetBackground = null;
	if (tabContent.css('display') == 'none') {
		tabContent.css({'opacity' : '0'});
		Animation(document.getElementById(type+'_section_'+divName)).show().to('opacity', .95).duration(300).go();
		targetBackground = 'url('+imageUrl+'inventory/label_'+divName+'.png)';
	} else {
		tabContent.css({'display' : 'none'});
		targetBackground = 'url('+imageUrl+'inventory/label_'+divName+'_base.png)';
	}
	// tabLabel.setStyle( {'backgroundImage' : targetBackground} );
	tabLabel.css( {'background-image' : targetBackground} );
	return false;
}

// myspace allows us to post bulletins
function myspacePostBulletin(title, content)
{
    var message = opensocial.newMessage(content);
    message.setField(opensocial.Message.Field.TITLE, title);

//    message.setField(opensocial.Message.Field.BODY, text);
    if (open_social_version == 7)
    {
        message.setField(opensocial.Message.Field.TYPE, MyOpenSpace.PostTo.Targets.BULLETINS);
        os.postTo(MyOpenSpace.MySpaceContainer.OSToken, message, null, myspacePostBulletinCallback);
    }
    else
    {
        message.setField(opensocial.Message.Field.TYPE, opensocial.Message.Type.NOTIFICATION);
        opensocial.requestSendMessage(viewerId, message, myspacePostBulletinCallback);
    }
}

function myspacePostBulletinCallback(response)
{
    if (response != MyOpenSpace.PostTo.Result.SUCCESS)
    {
        // do the fail thing
        return;
    }
    // do the success thing.
}




function showError(msg) {
    return;
    var div = document.createElement("div");
    div.innerHTML = msg;
    $(div).css({
            'position': 'absolute',
                'top': '100px',
                'left': '100px',
                'background-color': '#ffffff',
                'border' : 'solid 1px #000000',         
                'overflow' : 'auto',
                'padding-top': '20px'
                }).height('300').width('300');

    var button = document.createElement("button");
    button.innerHTML='hide';
    button.onclick= function () {
        $(this.parentNode).remove();
    }
    $(button).css({
            'position': 'absolute',
                'top': '0px',
                'right': '10px'
                
                      
                  });
    
    $(div).append(button);
                  


    //    $(document).append(div);
        document.body.appendChild(div);

}
