function xbig_manager ()
{
	// "internal" methods (i.e. data parsing/management)
	this.initialise		= xbig_initialise;
	this.load_news_xml	= xbig_load_news_xml;

	// "external" methods (i.e. UI management)
	this.render_filters_div	= xbig_render_filters_div;
	this.render_links_div	= xbig_render_links_div;
	this.render_news_div	= xbig_render_news_div;
	this.render_recent_div	= xbig_render_recent_div;

	this.render_all		= xbig_render_all;

	// Attributes
	// 1: Standard DIVs
	this.links_div		= false;
	this.filters_div	= false;
	this.recent_div		= false;
	this.news_div		= false;

	// 2: Standard XML objects
	this.review_list_obj 	= false;
	this.links_obj		= false;
	this.news_obj		= false;

	// 3: "internal" variables
	this.game_cache		= false;
	this.initialised	= false;
	//this.review_xml_file	= 'review_list.xml';
	this.review_xml_file	= 'trim_xml.php';

	gbl_timer.mark ('xbig_manager instantiated');
}

function xbig_initialise (review_count, review_offset, news_count)
{
	var i		= 0;
	var rg_list 	= false;
	var rg_node	= false;
	var g_obj	= false;
	var t_str	= '';
	var n_str	= '';

	// 1: Load all the standard <div> elements
	// Management of content_div (et al) is left as an exercise for the caller...
	this.links_div		= new div_manager ('links_div');
	this.filters_div	= new div_manager ('filters_div');
	this.news_div		= new div_manager ('news_div');
	this.recent_div		= new div_manager ('recent_div');

	// 2: Load the data from review_list.xml
	this.review_list_obj 	= new xml_manager (this.review_xml_file);
	this.review_list_obj.set_attribute ('recent_games_expanded', 'yes');
	this.review_list_obj.set_attribute ('filters_expanded', 'yes');

	this.links_obj		= new xml_manager ('links.xml');

	// We then cache pointers to individual games to speed future lookups
	this.game_cache = new Object();
	rg_list = this.review_list_obj.get_elements_by_tag_name('game');

	for (i = 0; i < rg_list.length; i++)
	{
		rg_node = rg_list[i];
		t_str = rg_node.get_child_node_attribute ('id', 'blog_id', 'Not Found?');
		this.game_cache[t_str] = rg_node;

		// HACK HACK: the blog_id and xbig_id values should never clash, so we stuff them both into the same array
		t_str = rg_node.get_child_node_attribute ('id', 'xbig_id', 'Not Found?');
		this.game_cache[t_str] = rg_node;
	}

	// 3: Preparing the "news" XML utilises this.game_cache...
	this.load_news_xml (review_count, review_offset, news_count);

	this.initialised = true;
	gbl_timer.mark ('xbig_manager initialised');
}

function xbig_render_all ()
{
	// We use the current/default "expanded" settings when rendering all the divs
	this.render_links_div 	(false);
	this.render_filters_div	(-1);
	this.render_news_div	(false);
	this.render_recent_div	(false);
	gbl_timer.mark ('xbig_manager rendered');
}

function xbig_load_news_xml (review_count, review_offset, news_count, add_review_tags)
{
	var i		= 0;
	var xml_found	= false;
	var tmp_obj	= false;
	var t_array	= false;
	var t_node	= false;
	var g_node	= false;
	var xml_url	= '';
	var t_str	= '';
	var expanded	= '';
	var t_list	= false;

	// Set sane default values
	review_count 	= (typeof (review_count) 	!= 'undefined' 	? review_count 		: 10);
	review_offset 	= (typeof (review_offset) 	!= 'undefined' 	? review_offset 	: 0);
	news_count 	= (typeof (news_count) 		!= 'undefined'	? news_count 		: 10);

	try
	{
		xml_url = 'get_xbig_news.php?review_count=' + review_count + '&review_offset=' + review_offset + "&news_count=" + news_count;
		tmp_obj = new xml_manager ();
		xml_found = tmp_obj.load_from_url (xml_url, true);
		gbl_timer.mark ('xbig_manager news: XML load attempt 1 complete');
	}
	catch (err_obj)
	{
		xml_found = false;
	}

	if (!xml_found)
	{
		tmp_obj = new xml_manager ("get_xbig_news.php.example");
		gbl_timer.mark ('xbig_manager news: XML load attempt 2 complete');
	}
	gbl_timer.mark ('xbig_manager news: XML loaded');

	if (this.news_obj != false)
	{
		// This function can be re-called on the index page, if the user wants to scroll through older news articles
		// We therefore need to ensure continuity for the "Recent" sections and their "expanded" settings
		t_array = new Array ('new_comments', 'new_reviews');
		for (i = 0; i < t_array.length; i++)
		{
			t_str = t_array[i];

			// 1: read...
			t_node = this.news_obj.get_elements_by_tag_name(t_str)[0];
			expanded = t_node.get_attribute('expanded', 'yes');

			// 2: write!
			t_node = tmp_obj.get_elements_by_tag_name(t_str)[0];
			t_node.set_attribute('expanded', expanded);
		}
	}
	gbl_timer.mark ('xbig_manager: news: previous details cached');

	// To keep things quick/simple, we add the name of the game to the <id> node as an attribute
	// This is actioned for all three sections of the XML (new comments, new reviews, current game list)
	t_list = tmp_obj.get_elements_by_tag_name('id');
	for (i = 0; i < t_list.length; i++)
	{
		t_node = t_list[i];
		t_str = t_node.get_node_value();
		if (typeof (this.game_cache[t_str]) != 'undefined')
		{
			g_node = this.game_cache[t_str];
			t_node.set_attribute('name', g_node.get_child_node_value ('name'));
		}
		else
		{
			//alert ('Unable to find game ' + t_str);
			t_node.set_attribute('name', 'Unavailable in XML...');
		}
	}
	gbl_timer.mark ('xbig_manager news: parsed');

	this.news_obj = tmp_obj;
}

function xbig_render_filters_div (flip_visibility, filter_name)
{
	var i		= 0;
	var f_node	= false;
	var f_list	= false;

	if (flip_visibility != '-1')
	{
		if (this.review_list_obj.get_attribute('filters_expanded', 'yes') == 'yes')
			this.review_list_obj.set_attribute ('filters_expanded', 'no');
		else
			this.review_list_obj.set_attribute ('filters_expanded', 'yes');
	}

	if (filter_name)
	{
		// this.review_list_obj should never contain more than half a dozen or so filters, so we just use a 
		// brute force search instead of caching
		f_list	= this.review_list_obj.get_elements_by_tag_name ('filter', 2);

		for (i = 0; i < f_list.length; i++)
		{
			f_node = f_list[i];
			if (f_node.get_attribute('safe_name') == filter_name)
			{
				if (f_node.get_attribute('expanded', 'yes') == 'yes')
					f_node.set_attribute ('expanded', 'no');
				else
					f_node.set_attribute ('expanded', 'yes');
		
				break;
			}
		}
	}

	// Filter data is pre-calculated by merge.html and stored in review_list.xml under a filters/filter hierarchy
	str = this.review_list_obj.render_with_xsl ('xsl/gbl_filters_div.xsl');
	this.filters_div.set_content (str);
}

function xbig_render_links_div (flip_visibility)
{
	var str 	= '';

	// Keep things simple: there should only ever be one "links" node...
	// This means we're interacting with the top-level XML node...
	if (flip_visibility)
	{
		if (this.links_obj.get_attribute('expanded', 'yes') == 'yes')
			this.links_obj.set_attribute ('expanded', 'no');
		else
			this.links_obj.set_attribute ('expanded', 'yes');
	}

	str = this.links_obj.render_with_xsl ("xsl/gbl_links_div.xsl");
	this.links_div.set_content (str);
}

function xbig_render_recent_div (flip_visibility)
{
	var str 	= '';

	// Keep things simple: there should only ever be one "links" node...
	// This means we're interacting with the top-level XML node...
	if (flip_visibility)
	{
		if (this.review_list_obj.get_attribute('recent_games_expanded', 'yes') == 'yes')
			this.review_list_obj.set_attribute ('recent_games_expanded', 'no');
		else
			this.review_list_obj.set_attribute ('recent_games_expanded', 'yes');
	}

	str = this.review_list_obj.render_with_xsl ("xsl/gbl_recent_div.xsl");
	this.recent_div.set_content (str);
}

function xbig_render_news_div (subsection)
{
	var str 	= '';
	var t_node	= false;

	if (subsection)
	{
		t_node = this.news_obj.get_elements_by_tag_name(subsection)[0];

		if (t_node.get_attribute('expanded', 'yes') == 'yes')
			t_node.set_attribute ('expanded', 'no');
		else
			t_node.set_attribute ('expanded', 'yes');
	}

	str = this.news_obj.render_with_xsl ("xsl/gbl_news_div.xsl");
	this.news_div.set_content (str);
}

function load_search_engine (filter_safe_name, tag_name)
{
	var tag_safe_name = sanitise_str (tag_name);
	var url = 'search.html?filter_name=' + filter_safe_name + '&tag_name=' + tag_safe_name;
	window.location = url;
}

function submit_text_search (ev_obj)
{
	var t_node	= false;
	var str		= '';
	var url		= '';

	//alert (ev_obj +': ' + ev_obj.keyCode);
	// Simple helper to get around IE/Mozilla differences.  IE uses window.event, Mozilla uses event
	if (!ev_obj ||ev_obj.keyCode == 13)
	{
		// Extract the text from the input field
		t_node	= document.getElementById('search_text');
		str	= escape (t_node.value);

		url	= 'search.html?search_text=' + str;
		window.location = url;
	}
}

function submit_tag_search (filter_name, tag_str)
{
	var url		= '';

	// Extract the text from the input field
	tag_str	= sanitise_str (tag_str);
	url	= 'search.html?filter_name=' + filter_name + '&tag_name='+ escape(tag_str);
	window.location = url;
}

