/* jslint verified 2008.11.19 */
/*jslint browser: true, onevar: false, undef: true, white: false, eqeqeq: true */
/*globals $, $$, Ajax, Constants, $_GET, isset, statusBar, Song, User, Flash,
	setupTop, selectMed, setupMedRow, selectMedRow, setupDetailRow, selectDetailRow, setupTop, selectTop, setupMed, preload, addHoverEvents, selectDetail, doSearch, showLoadingBar, searchSucceeded, searchFailed, buildPaging, buildPageLink */
var Discover = function() {
	var selectedTop, selectedMedRow, selectedMed, selectedDetailRow, selectedDetail,
		medRows, detailRows = [], lastSearch = '', pauseSearching = false, page = 0,
		resultsHolder, numPerPage = 10,
		ids = {
			top: 'topLevel', med: 'medLevel', topGenres: 'topGenres', topInstruments: 'topInstruments',
			topUsers: 'topUsers', results: 'results'
		}, classes = {
			selected: 'selectorSelected', hover: 'selectorHover', disabled: 'disabled',
			paging: 'paging', pagingLink: 'pagingLink', pagingDisabled: 'pagingDisabled',
			pagingSelected: 'pagingSelected', loadingBar: 'loadingBar'
		}, msgs = {
			// 171 = <<, 187 = >>
			previous: String.fromCharCode(171) + ' previous', next: 'next '+ String.fromCharCode(187),
			loading: 'Loading...'
		};

	function setup() {
		resultsHolder = $(ids.results);
		var top = $(ids.top),
			med = $(ids.med),
			topOptions = top.getElementsByTagName('td'),
			i, t = $_GET('t'), r = $_GET('r'),
			tops = {song: 0, stem: 1, user: 2},
			meds = {popular: 0, played: 1, recent: 2},
			startTop = isset(typeof(tops[t])) ? tops[t] : tops.stem,
			startMed = isset(typeof(meds[r])) ? meds[r] : meds.recent;
		for (i=0; i<topOptions.length; ++i) {
			setupTop($$(topOptions[i]));
		}

		medRows = med.rows;
		for (i=0; i<medRows.length; ++i) {
			setupMedRow($$(medRows[i]));
		}

		detailRows.push($(ids.topGenres));
		detailRows.push($(ids.topInstruments));
		detailRows.push($(ids.topUsers));
		for (i=0; i<detailRows.length-1; ++i) {
			setupDetailRow(detailRows[i]);
		}

		selectTop(topOptions[startTop]);
		selectMed(medRows[startTop].cells[startMed]);

		preload();
	}

	function setupTop(el) {
		el.addClick(function() { selectTop(el); });
		addHoverEvents(el);
	}

	function addHoverEvents(el) {
		el.addEvent('mouseover', el.addClassName.bind(el, classes.hover));
		el.addEvent('mouseout', el.removeClassName.bind(el, classes.hover));
	}

	function setupMedRowCell(cell) {
		cell.addClick(function() { selectMed(cell); });
		addHoverEvents(cell);
	}
	function setupMedRow(el) {
		for (var i=0; i<el.cells.length; ++i) {
			setupMedRowCell($$(el.cells[i]));
		}
	}

	function setupDetailRowCell(cell) {
		cell.addClick(function() { selectDetail(cell); });
		addHoverEvents(cell);
	}
	function setupDetailRow(el) {
		for (var i=0; i <el.rows[0].cells.length; ++i) {
			setupDetailRowCell($$(el.rows[0].cells[i]));
		}
	}

	function selectTop(el) {
		if (selectedTop !== el) {
			if (selectedTop) {
				selectedTop.removeClassName(classes.selected);
			}
			el.addClassName(classes.selected);
			selectedTop = el;

			pauseSearching = true;
			selectMedRow(medRows[el.cellIndex]);
			selectDetailRow(detailRows[el.cellIndex]);
			pauseSearching = false;
			doSearch();
		}
	}

	function selectMedRow(el) {
		if (selectedMedRow !== el) {
			if (selectedMedRow) {
				selectedMedRow.hide();
			}
			selectedMedRow = el;
			selectedMedRow.show('block', /* is table */ true);

			selectMed($$(selectedMedRow.cells[0]));
		}
	}

	function selectMed(el) {
		if (selectedMed !== el) {
			if (selectedMed) {
				selectedMed.removeClassName(classes.selected);
			}
			selectedMed = el;
			selectedMed.addClassName(classes.selected);
			page = 0;
			doSearch();
		}
	}

	function selectDetailRow(el) {
		if (selectedDetailRow !== el) {
			if (selectedDetailRow) {
				selectedDetailRow.hide();
			}
			selectedDetailRow = el;
			selectedDetailRow.show('block', /* is table */ true);

			selectDetail(null);
		}
	}

	function selectDetail(el) {
		if (selectedDetail) {
			selectedDetail.removeClassName(classes.selected);
		}
		if (selectedDetail !== el) {
			selectedDetail = el;
			if (el !== null) {
				selectedDetail.addClassName(classes.selected);
			}
		} else {
			selectedDetail = null;
		}
		page = 0;
		doSearch();
	}

	function doSearch() {
		if (!pauseSearching) {
			var top = selectedTop.getAttribute('title'),
				med = selectedMed.getAttribute('title'),
				detail = selectedDetail ? selectedDetail.id : '',
				thisSearch = [top,med,detail,page].join(','),
				ajax;
			if (thisSearch !== lastSearch) {
				Flash.stop('smallPlayerHidden');
				showLoadingBar();
				ajax = new Ajax(Constants.ajax() + 'discover',
					{
						method:'get',
						onSuccess:searchSucceeded,
						onFailure:searchFailed,
						parameters: ['t='+top,'r='+med,'d='+detail,'page='+page].join('&')
					}
				);
				ajax.send();
				lastSearch = thisSearch;
			}
		}
	}

	function showLoadingBar() {
		resultsHolder.addClassName(classes.disabled);
		var w = resultsHolder.clientWidth, h = resultsHolder.clientHeight,
			loadingBar = document.create('div', null, classes.loadingBar,
			'<table width="100%"><tr>' +
				'<td valign="middle" width="'+w+'" height="'+h+'"><div>' +
					msgs.loading + '<br><img src="'+Constants.images()+'blueLoadingBar.gif" />' +
			'</div></td></tr></table>');
		resultsHolder.appendChild(loadingBar);
	}

	function searchSucceeded(request) {
		var response = JSON.parse(request.responseText),
			thisSearch = [response.type,response.restrict,response.detail,response.page].join(','),
			id;
		if (thisSearch === lastSearch) {
			resultsHolder = $(ids.results).empty();
			resultsHolder.appendChild(buildPaging(response.page, response.count));
			if (response.type === 'song' || response.type === 'stem') {
				// Make sure we're dealing with an object and not an array
				if (!isset(typeof(response.songs.splice))) {
					for (id in response.songs) {
						if (response.songs.hasOwnProperty(id)) {
							resultsHolder.appendChild(new Song(id, response.songs[id], (response.type === 'stem'), Song.style.large));
						}
					}
				}
			} else if (response.type === 'user') {
				// Make sure we're dealing with an object and not an array
				if (!isset(typeof(response.users.splice))) {
					for (id in response.users) {
						if (response.users.hasOwnProperty(id)) {
							resultsHolder.appendChild(new User(id, response.users[id], User.style.large));
						}
					}
				}
			}
			resultsHolder.appendChild(buildPaging(response.page, response.count));
			resultsHolder.removeClassName(classes.disabled);
		}
	}

	function setPage(p) {
		page = p;
		doSearch();
	}

	function buildPaging(pageIndex, count) {
		var numPages = Math.ceil(count / numPerPage),
			indexSoFar = 0, i,
			paging = document.create('div').classify(classes.paging),
			previousActive = pageIndex > 0,
			nextActive = pageIndex < (numPages-1),
			next = document.create('span', null,
				(nextActive ? classes.pagingLink : classes.pagingDisabled), msgs.next),
			previous = document.create('span', null,
				(previousActive ? classes.pagingLink : classes.pagingDisabled), msgs.previous);
		if (previousActive) {
			previous.addClick(function() { setPage(pageIndex-1); });
		}
		paging.appendChild(previous);
		if (pageIndex < 5) {
			for (i=0; i<Math.min(5, pageIndex+1); ++i) {
				paging.appendChild(buildPageLink(i, (i === pageIndex)));
			}
			indexSoFar = i;
		} else {
			paging.appendChild(buildPageLink(0, false));
			paging.appendChild(document.create('span', null, classes.pagingLink, ' ... '));
			for (i=(pageIndex-2); i<=pageIndex; ++i) {
				paging.appendChild(buildPageLink(i, (i === pageIndex)));
			}
			indexSoFar = i;
		}
		if (numPages < (pageIndex + 6)) {
			for (i=indexSoFar; i<numPages; ++i) {
				paging.appendChild(buildPageLink(i, (i === pageIndex)));
			}
		} else {
			for (i=indexSoFar; i<(pageIndex+3); ++i) {
				paging.appendChild(buildPageLink(i, (i === pageIndex)));
			}
			paging.appendChild(document.create('span', null, classes.pagingLink, ' ... '));
			paging.appendChild(buildPageLink(numPages-1, false));
		}
		if (nextActive) {
			next.addClick(function() { setPage(pageIndex+1); });
		}
		paging.appendChild(next);
		return paging;
	}

	function buildPageLink(pageIndex, selected) {
		var linkClass = selected ? classes.pagingSelected : classes.pagingLink,
			pageLink = document.create('span', null, linkClass, (pageIndex + 1));
		if (!selected) {
			pageLink.addClick(function() { setPage(pageIndex); });
		}
		return pageLink;
	}

	function searchFailed(request) {
		statusBar.error('Sorry, your search failed. Please try again');
	}

	function preload() {
		var imgs = ['blueLoadingBar.gif'], img, i;
		for (i=0; i<imgs.length; ++i) {
			img = new Image();
			img.src = Constants.images() + imgs[i];
		}
	}

	window.addLoad(setup);
}();
