/* 
	Deals with the RHN in the browser for navigating the hierarchy within a set of results.
	
	Slides panels in an out on the right, and loads the matching content into the main page.

	Requires glow.dom, glow.events, glow.anim, glow.net.

	Requires global variables:
		gb_qe_num_of_last_toplevel_filter = number of last top-level (text/usr/tag) filter used in QE submissions search url in browse_view.sssi

	created: 2008-10-03 <a href="mailto:Michael.Taylor1@bbc.co.uk">Mike Taylor</a>
*/
/*
	Notes: 
		- there is a similar list for levels 3 and 4, except that at level 4 the selected topic is not a link
*/

var blast_slider = (function(){

	if (!window['glow']) 
		return null;

// MAINTAINED VARIABLES:
	var g_gallery = {} // gallery object
		, g_a_listener_ids = [] // save these so we can remove them again
		, g_n_seconds_for_slide = 1.0 // seconds for set to slide in/out
		, g_s_slider_container_selector = '#filter-and-search ul.categories' /* selector for block containing nested taxonomy list */
		, g_ni_slider = [] /* nodelist for above */
		, g_s_results_container_selector = '#vision-gallery-view' /* selector for browse results */
		, g_ni_results = [] /* nodelist for above */
		, g_re_count = / \((\d+)\)/ /* match a count inside an div containing an input button */
		, g_o_fm = {} // [name]->[value] for categories form
		, g_re_cat = /^sub_(cat\d{1,2})/ //  get target cat from name (subject is button value)
		, g_re_sub_cat = /^top_(sub\d{1,2}_(cat\d{1,2}))/ //  get target cat + sub from id (topic is button value)
		, g_s_fm_filter_med = '#fm-media-filter' // selector for media filter form
		, g_s_fm_filter_loc = '#fm-location-filter' // selector for location filter
		, g_ni_fm_filter_med = [] // media filter
		, g_ni_fm_filter_loc = [] // location filter
		, g_b_changing_taxnav = false // set true while making changes to taxonomy filter (NOT concerned with gallery status)
		;

// FUNCTIONS:

	/* 
		return object containing new taxonomy (mainly to avoid nested ifs)
	*/
	function new_taxonomy(ni_src) {

		var dbg = 0
			, o_tax = { 'cat':'', 'sub':'', 'top':'' } // taxonomy (return value)
			, a_match = [] // matches to above RegExp
			, i_cat = 0	// 1-based level numbering applied to taxonomy
			, i_sub = 0
			, i_top = 0
			;

		if (ni_src.hasClass('up-to-categories')) {  // go to top level (leave everything blank)
			return o_tax; 
		}
		
		// go to taxonomy
		if (ni_src[0].name == 'cat') {
			o_tax['cat'] = ni_src.val();
			return o_tax;
		} 
		
		// get category where subject is value
		a_match = g_re_cat.exec(ni_src[0].name);
		if (a_match) {

			if (dbg) { alert("Matched category=[" + a_match[1] + "] with subject value [" + ni_src.val() + "]"); }

			o_tax['cat'] = g_o_fm[a_match[1]];
			o_tax['sub'] = ni_src.val();

			return o_tax;
		}
		// get subject + category where topic is value
		a_match = g_re_sub_cat.exec(ni_src[0].name);
		if (a_match) {

			if (dbg) { alert("Matched subject=[" + a_match[1] + "] category=[" + a_match[2] + "]"); }

			o_tax['cat'] = g_o_fm[a_match[2]];
			o_tax['sub'] = g_o_fm[a_match[1]];
			o_tax['top'] = ni_src.val();

			return o_tax;
		}

		if (dbg) { alert('Could not deduce target taxonomy'); }

		return o_tax;
	}
	//-----

	/* 
		return part of a QE query string (without any separators)
	*/
	function filter(n, attrib, oper, val) {

		return 'attrib_' + n + '=' + attrib
			+ ';oper_' + n + '=' + oper
			+ ';val_' + n + '=' + val
			;
	}
	//-----

	/* 
		reload gallery when taxonomy changes
		ni_src: input button clicked on
	*/
	function reload_taxonomy(ni_src, o_tax) {

		var dbg = 0
			, i = gb_qe_num_of_last_toplevel_filter // count for QE filters
			, qe_tax_filters = ''	// QE filters relating to taxonomy
			, qe_non_tax_filters = '' // QE filters relating to media/location
			, qe_fwd_tax = '' // parameters relating to taxonomy
			, qe_fwd_non_tax = '' // parameters relating to media/location
			;

		if (dbg) { alert('Reloading taxonomy'); }

		// we don't need or want to change top level filters, nor 'qe_base' (view/pagesize) here.
		// "lower" filters (medium/location) must be reset:

		// NOTE: compare these will filters in browse_view.sssi - the attrib numbers must match!

		reset_other_filters_for_new_tax(o_tax);

		g_b_changing_taxnav = false; // changes to filter etc are now done - rest relates to gallery

		qe_non_tax_filters = filter(++i, 'file_type', 'eq', '');
		qe_non_tax_filters += ';' + filter(++i, 'user_location', 'eq', '');

		qe_tax_filters = filter(++i, 'tag_type', 'eq', 'ugc');
		qe_tax_filters += ';' + filter(++i, 'category', 'eq', encodeURIComponent(o_tax['cat']));
		qe_tax_filters += ';' + filter(++i, 'subject', 'eq', encodeURIComponent(o_tax['sub']));
		qe_tax_filters += ';' + filter(++i, 'topic', 'eq', encodeURIComponent(o_tax['top']));

		qe_fwd_non_tax = 'med=;loc=';
		qe_fwd_tax = 'cat=' + encodeURIComponent(o_tax['cat']) 
			+ ';sub=' + encodeURIComponent(o_tax['sub']) 
			+ ';top=' + encodeURIComponent(o_tax['top'])
			;

		if (dbg) { alert('Going to cat[' + o_tax['cat'] + '] sub[' + o_tax['sub'] + '] top[' + o_tax['top'] + ']'
			+ '\nfilters:\n' + qe_non_tax_filters + ';' + qe_tax_filters
			+ '\nfwd:\n' + qe_fwd_non_tax + ';' + qe_fwd_tax
			); }

		g_gallery.reload({
			  'qe_non_tax_filters': qe_non_tax_filters
			, 'qe_tax_filters': qe_tax_filters
			, 'qe_fwd_non_tax': qe_fwd_non_tax
			, 'qe_fwd_tax': qe_fwd_tax
		});
	}
	//-----

	/* 
		Reset location filter to default.
	*/
	function reset_location_filter() {

		var dbg = 0
			, ni_loc_opts = [] // location options
			;

		ni_loc_opts = glow.dom.get(g_ni_fm_filter_loc[0]['loc']).get('option'); // location options
		ni_loc_opts.each(function(i) {
			if (this.selected)
				ni_loc_opts.slice(i, i+1).removeAttr('selected');
		});
		ni_loc_opts[0].selected = 'selected';
	}
	//-----

	/* 
		Reset media filter (including hidden value in location form) to default ('All')
	*/
	function reset_media_filter() {

		var dbg = 0
			, ni_all_media = [] // all-media button
			, ni_selected = [] // currently selected button (container)
			, ni_selected_input = [] // actual button in above
			, src = '' // source parameter of image button
			;

		// clear any filters set in media form
		ni_all_media = g_ni_fm_filter_med.get('.med-btn-all');
		if (!ni_all_media.hasClass('selected')) {

			if (dbg > 1) alert('All media NOT selected');

			ni_all_media.addClass('selected');

			ni_selected = g_ni_fm_filter_med.get('.med-btn.selected');
			if (dbg > 1) alert('Found [' + ni_selected.length + '] selected buttons with value ' + ni_selected.get('input').val());

			if (ni_selected.length) {
				ni_selected.removeClass('selected');
				ni_selected_input = ni_selected.get('input');
				src = ni_selected_input.attr('src');
				ni_selected_input.attr('src', src.replace('_selected', ''))
			}
		}

		// clear corresponding value in location form
		g_ni_fm_filter_loc[0]['med'].value = '';
	}
	//-----

	/* 
		reset lower filters to the new values.
	*/
	function reset_other_filters_for_new_tax(o_tax) {

		var dbg = 0
			;

		if (dbg > 1) alert('Resetting other filters'
			+ '\nMedia form Buttons: [' + g_ni_fm_filter_med.get('.med-btn').length + ']'
			+ '\nLocation form Select: [' + g_ni_fm_filter_loc.get('select').length + ']'
			);

		reset_media_filter();
		reset_location_filter();

		// set the new taxonomy values in hidden fields
		for (var fld in o_tax)
		{
			g_ni_fm_filter_med[0][fld].value = o_tax[fld];
			g_ni_fm_filter_loc[0][fld].value = o_tax[fld];
		}
	}
	//-----

	/* 
		slide in the given target item.
	*/
	function slide_in(ni_src, ni_trg, o_tax) {

		var dbg = 0
			, anim = null // the animation
			, fn_complete = null // on completion
			, s_to_left = '0'
			;

		if (dbg) { alert('Slide in in [' + g_n_seconds_for_slide + '] seconds'); }

		g_gallery.loading();

		// to 0 for higher levels, but 
		if (ni_trg.hasClass('topics'))
			s_to_left = '20px';

		anim = glow.anim.css(ni_trg, g_n_seconds_for_slide
			, { 'left': {to: s_to_left } }
			, { 'tween': glow.tweens.easeBoth() }
		);

		fn_complete = function() { 
			ni_trg
				.addClass('selected').addClass('js-selected')
				.css('z-index', '').css('visibility', '').css('left', ''); 

			reload_taxonomy(ni_src, o_tax);
		};
		glow.events.addListener(anim, 'complete', fn_complete);

		ni_trg.css('z-index', '1').css('visibility', 'visible');
		anim.start();
	}
	//-----

	/* 
		slide out the given target item.
		ni_src: input item clicked
		ni_trg: the input item to be slid out
	*/
	function slide_out(ni_src, ni_trg, o_tax) {

		var dbg = 0
			, anim = null // the animation
			, fn_complete = null // on completion
			;

		if (dbg) { alert('Slide out in [' + g_n_seconds_for_slide + '] seconds'); }

		g_gallery.loading();

		anim = glow.anim.css(ni_trg, g_n_seconds_for_slide
			, { 'left': {to: '193px'} }
			, { 'tween': glow.tweens.easeBoth() }
		);

		fn_complete = function() { 
			ni_trg.removeClass('selected').removeClass('js-selected')
				.css('left', ''); 

			// we may need to reset lower levels as well
			ni_trg.get('ul').removeClass('selected').removeClass('js-selected');

			reload_taxonomy(ni_src, o_tax);
		};

		glow.events.addListener(anim, 'complete', fn_complete);
		anim.start();
	}
	//-----

	/* 
		handle clicking on a button in the location filter.
	*/
	function on_location_set(g_evt) {

		if (g_gallery.is_reloading() || g_b_changing_taxnav) { return false; }// do nothing

		if (!g_evt.source) { return true; } // follow link

		var dbg = 0
			, ni_src = glow.dom.get(g_evt.source) // the input btn
			, i = gb_qe_num_of_last_toplevel_filter // count for QE filters
			, qe_non_tax_filters = '' // non-taxonomy QE filters
			, qe_fwd_non_tax = '' // non-taxonomy parameters
			, med = '' // currently selected medium (video, etc)
			, loc = '' // selected option for location
			;

		if ((ni_src[0].nodeName).toLowerCase() != 'input') {
			if (dbg) { alert('Type not input: ' + ni_src[0].nodeName); }
			return true;
		}

		if (dbg) { alert('Location: ' + loc + ':' + ni_src[0].nodeName + ':' + ni_src[0].id + ':' 
			+ ni_src[0].className + ':' + ni_src[0].name + ':' + ni_src[0].value); }

		g_b_changing_taxnav = true;
		g_b_changing_taxnav = false; // we don't make any changes to the filter itself with JS in this case.

		// set query filter
		loc = g_ni_fm_filter_loc.get('select').val();
		loc = glow.dom.get('#fm-location-filter select').val();
		med = g_ni_fm_filter_loc[0]['med'].value;

		qe_non_tax_filters = filter(++i, 'file_type', 'eq', med);
		qe_non_tax_filters += ';' + filter(++i, 'user_location', 'eq', encodeURIComponent(loc));

		qe_fwd_non_tax = 'med=' + med + ';loc=' + encodeURIComponent(loc);

		g_gallery.loading();
		g_gallery.reload({
			  'qe_non_tax_filters': qe_non_tax_filters
			, 'qe_fwd_non_tax': qe_fwd_non_tax
		});

		return false;
	}
	//-----

	/* 
		handle clicking on a button in the media filter.
	*/
	function on_media_click(g_evt) {

		if (g_gallery.is_reloading() || g_b_changing_taxnav) { return false; }// do nothing

		if (!g_evt.source) { return true; } // follow link

		var dbg = 0
			, ni_src = glow.dom.get(g_evt.source) // the input btn
			, src = '' // source parameter image submit button
			, i = gb_qe_num_of_last_toplevel_filter // count for QE filters
			, val = '' // set to value assigned to med in query
			, qe_non_tax_filters = '' // non-taxonomy QE filters
			, qe_fwd_non_tax = '' // non-taxonomy parameters
			;

		if ((ni_src[0].nodeName).toLowerCase() != 'input') {
			if (dbg) { alert('Type not input: ' + ni_src[0].nodeName); }
			return true; // follow link
		}

		if (ni_src.parent().hasClass('selected')) {
			return false; // already selected
		}

		g_b_changing_taxnav = true; // block further clicks until we've finished changing the filter

		val = (ni_src[0].value).toLowerCase();
		if (val == 'images') {
			val = 'image'; // deduce filter value from display value
		}

		// clear both filters before setting new values
		reset_media_filter();
		reset_location_filter();

		if (val == 'all') {
			qe_non_tax_filters = filter(++i, 'file_type', 'eq', '');
			qe_fwd_non_tax = 'med=';
		}
		else {
			// mark the image submit button as selected, adding class and replacing src
			g_ni_fm_filter_med.get('.med-btn-all').removeClass('selected');
			ni_src.parent().addClass('selected');
			src = ni_src.attr('src');
			ni_src.attr('src', src.replace(/_(\d+x\d+)/, '_selected_$1'));

			qe_non_tax_filters = filter(++i, 'file_type', 'eq', val);
			qe_fwd_non_tax = 'med=' + val;
		}

		// set the new taxonomy values in hidden fields
		g_ni_fm_filter_loc[0]['med'].value = val;

		if (dbg) { alert('Media: ' + ni_src[0].id + ':' + ni_src[0].className + ':' + ni_src[0].name + ':' + ni_src[0].value); }

		g_b_changing_taxnav = false; // we've finished making changes to the taxonomy nav

		// set up the new query parameters
		qe_non_tax_filters += ';' + filter(++i, 'user_location', 'eq', '');
		qe_fwd_non_tax += ';loc=';

		g_gallery.loading();
		g_gallery.reload({
			  'qe_non_tax_filters': qe_non_tax_filters
			, 'qe_fwd_non_tax': qe_fwd_non_tax
		});

		return false;
	}
	//-----

	/* 
		handle clicking on an the RHN for navigating the taxonomy.
		This function is complicated, partly because of confusion in the UI design at the lowest level.
		When no sliding happens, the taxonomy reload and gallery dimming must be called directly here,
		instead of in the slider functions.
		Note: before we change any src items, we need to extract the taxononmy values.

		There are 3 cases: to-parent, to-child, to-sibling (topic only).
		The complication is at subject or topic level (when viewing a list of topics).
		In this case, the 'SUBJECTS' button's "to-parent" must be changed, depending on whether we are at 'subject'
		level (all topics listed & selectable) or at 'topic' level (that topic not selectable).

		Possible states of a topic button:
		<input id="btn-1-2-3" class="submit" type="submit" name="top_sub2_cat3" value="Animation" />
		<input id="btn-1-2-3" class="submit topic-active this-active" type="submit" name="top_sub2_cat3" value="Animation" />
		<input id="btn-1-2-3" class="submit topic-active" type="submit" name="top_sub2_cat3" value="Animation" />

		Alternative versions of 'Subject' button:
		<input class="up-to-topics" alt="Topics in this subject" type="image" name="sub_cat3" value="{{cgiparam.sub}}" />
		<input class="up-to-subjects" alt="Subjects in this category" type="image" name="cat" value="{{cgiparam.cat}}" />

	*/
	function on_slider_click(g_evt) {

		if (g_gallery.is_reloading() || g_b_changing_taxnav) { return false; }// do nothing

		if (!g_evt.source) { return true; } // follow link

		var dbg = 0
			, ni_src = glow.dom.get(g_evt.source) // the input btn
			, ni_trg  = [] // object to be activated
			, ni_container = [] // the nearest UL found UP the tree from the source element (containing links + up btn)
			, a_match = null // result of matching regexp
			, ni_subject_btn = [] // 'SUBJECT' button (vertical 'up' button with 2 actions)
			, s_btn_name = '' // name to be assigned to 'SUBJECT' button
			, o_tax = {} // new taxonomy requested by button clicked
			;

		// NOTE: hierarchies:
		//	- for standard down links: [[ul / li] / ul / li] / ul / li / div / input
		//	- for up links:            [[ul / li] / ul / li] / ul / li /input

		if ((ni_src[0].nodeName).toLowerCase() != 'input') {
			if (dbg) { alert('Type not input: ' + ni_src[0].nodeName); }
			return true;
		}

		g_b_changing_taxnav = true; // block further clicks until this is cleared

		o_tax = new_taxonomy(ni_src); // save the new taxonomy

		if (dbg) { alert('clicked ' 
			+ g_evt.source.nodeName + ' (' + g_evt.source.id + ':' 
			+ g_evt.source.className + ':'
			+ ni_src.val()
			+ ')'); }

		// Case 1: 'up' to list of categories (top level) or list of subjects (category level)
		if (ni_src.hasClass('up-to-categories') || ni_src.hasClass('up-to-subjects')) {

			// The easy case - go up one level.
			ni_trg = ni_src.parent().parent();
			slide_out(ni_src, ni_trg, o_tax);			

// EARLY RETURN:
			return false;

		}

		// Case 2: 'up' to list of topics (subject level)
		// Happens ONLY happens when a TOPIC is currently selected.
		// We do no sliding, and need to restore the 'SUBJECTS' button to 'up-to-subject',
		// and clean up by restoring all topics to 'deselected' state.
		if (ni_src.hasClass('up-to-topics')) { 

			// Restore the SUBJECTS button back to a 'view subjects' button (i.e. select a category):
			ni_src.removeClass('up-to-topics').addClass('up-to-subjects');

			ni_container = ni_src.parent().parent(); 

			// go up to the sister button to this category and imitate it
			var ni_category = ni_container.parent().parent().parent().get('> .submit-btn input');
			ni_src[0].name = ni_category[0].name;
			ni_src[0].value = ni_category[0].value;

			// Restore the topic links to default values
			ni_container = ni_src.parent().parent(); // the UL containing SUBJECTS button and topics links
			ni_container.get('.can-activate .submit-btn').removeClass('submit-btn-inactive');
			ni_container.get('.submit-btn input').removeClass('topic-active').removeClass('this-active');

			g_b_changing_taxnav = false;
			g_gallery.loading();
			reload_taxonomy(ni_src, o_tax);

// EARLY RETURN:
			return false;
		}

		// All 'UP' cases now dealt with. So we are going DOWN or SIDEWAYS from a standard link.

		// Case 3: if there is a child list of our list item, move to it (common case)
		ni_trg = ni_src.parent().parent().get('> ul'); // ul child of our parent li
		if (ni_trg.length > 0) {
			slide_in(ni_src, ni_trg, o_tax);			
// EARLY RETURN:
			return false;
		}

		// Cases 4 & 5: there is no child list, so we are viewing a topic list. 
		// Either select one (if not selected), or switch to a sibling. No sliding needed! 
		// 'Target' is essentially the container of 'source'.

		ni_trg = ni_src.parent(); // this is the div.submit-btn containing our source input button
		ni_container = ni_trg.parent().parent(); // UL containing topics + SUBJECTS btn
		ni_container.get('.can-activate .submit-btn').removeClass('submit-btn-inactive');

		if (ni_src.hasClass("topic-active")) { // already filtered down to topic

			if (ni_src.hasClass("this-active")) {
// EARLY RETURN:
				g_b_changing_taxnav = false;
				return false;// DON'T RELOAD TAXONOMY (or do anything else)
			}

			// restore button for selected topic (currently marked inactive) to the same state as the others
			ni_container.get('.this-active').removeClass('this-active').parent().removeClass('submit-btn-inactive');
		} 
		else { // No topic active: filter down to topic

			// the vertical 'Subject' button must now point to a subject, not a category:
			ni_subject_btn = ni_container.get('.subject-btn input');
			ni_subject_btn.removeClass('up-to-subjects').addClass('up-to-topics');

			// mark all buttons to show a topic is selected
			ni_container.get('.submit-btn input').addClass('topic-active');

			// we need the subject name and its category number
			// we can get this from the subject selection btn which is sister to our ul
			var ni_subject = ni_container.parent().get('> .submit-btn input');
			ni_subject_btn[0].name = ni_subject[0].name;
			ni_subject_btn[0].value = ni_subject[0].value;
		}

		// mark parent and child to show this topic is selected
		ni_trg.addClass('submit-btn-inactive');
		ni_src.addClass('this-active');

		g_b_changing_taxnav = false;
		g_gallery.loading();
		reload_taxonomy(ni_src, o_tax);
		return false;
	}
	//-----

	/* 
		setup the listeners.
	*/
	function setup_slider() {

		var dbg = 0
			, msg = ''
			, ni_tax_flds = []
			, fld_name = '' // for debug output
			;

		g_a_listener_ids.push(
			  glow.events.addListener(g_ni_slider, 'click', function(g_evt) { return on_slider_click(g_evt); })
			, glow.events.addListener(g_ni_fm_filter_med, 'click', function(g_evt) { return on_media_click(g_evt); })
			, glow.events.addListener(g_ni_fm_filter_loc[0]['set_location'], 'click', function(g_evt) { return on_location_set(g_evt); })
		);

		ni_tax_flds = glow.dom.get('#fm-tax-filter input.lookup');
		ni_tax_flds.each(function(i) { g_o_fm[this.name] = this.value; });

		if (dbg) {
			msg = '';
			for (fld_name in g_o_fm)
			{
				msg += '\n' + fld_name + ':' + g_o_fm[fld_name];
			}
			alert('Values:\n' + msg);
		}
	}
	//-----

	slider = {

		// set up the gallery
		init: function(
			  gallery // blast gallery object
			) {

			var dbg = 0
				;

			g_gallery = gallery;

			g_ni_slider = glow.dom.get(g_s_slider_container_selector);
			g_ni_results = glow.dom.get(g_s_results_container_selector) 

			g_ni_fm_filter_med = glow.dom.get(g_s_fm_filter_med);
			g_ni_fm_filter_loc = glow.dom.get(g_s_fm_filter_loc);

			if (dbg) { alert('Found ' + g_ni_slider.length + ' slider (' + g_s_slider_container_selector + ')\n'
				+ ' Found ' + g_ni_results.length + ' result blocks (' + g_s_results_container_selector + ')'); }

			// get the navigation buttons
			setup_slider();

		},
		//-----

		dummy_field: null // so we can have trailing commas on the other fields
	};

	return slider;

})(); // call immediately

// end of script
