var Result = Class.create ();
Result.prototype = {
	initialize: function (container, jsonObj) {
		this.container = container;
		this.jsonObj = jsonObj;
		Object.extend(this, TemplatedElement);
		this._buildFromTemplate('template_result');
		this.div = this.element;

		this.elementLength.innerHTML = this.jsonObj.length_seconds;
		this.elementTitle.innerHTML = this.jsonObj.title;
		this.thumbnail.src = this.jsonObj.thumbnail_url;
		this.thumbnail.title = this.jsonObj.title;

		this.ratingStar = new Array (this.ratingStar0, this.ratingStar1, this.ratingStar2, this.ratingStar3, this.ratingStar4, this.ratingStar5);

		var round_rating = Math.round(2 * this.jsonObj.rating_avg);
		for (var i = 0; i < 5; i ++) {
			this.ratingStar[i].title = 'Rating: ' + this.jsonObj.rating_avg;
			Element.removeClassName (this.ratingStar[i], 'half');
			Element.removeClassName (this.ratingStar[i], 'full');
			Element.removeClassName (this.ratingStar[i], 'none');
			var s = round_rating - (2*i);
			if (s < 1) 	Element.addClassName (this.ratingStar[i], 'none'); else
			if (s == 1)	Element.addClassName (this.ratingStar[i], 'half');
			else		Element.addClassName (this.ratingStar[i], 'full');
		}

		if (this.container.showFavorites)
			Element.addClassName (this.element, 'favorite');

		if (this.jsonObj.ytdeleted) // for favorites
			Element.addClassName(this.element, 'ytdeleted');
		else if (this.jsonObj.isprivate)
			Element.addClassName (this.element, 'isprivate');

		this.container.element.appendChild(this.element);

		this.element.onmouseover = this.hoverResult.bindAsEventListener(this);
		this.element.onmouseout = this.unhoverResult.bindAsEventListener(this);

		this.resize(this.container.results_size, this.container.results_font_size);

		this.btnPlay.onmouseover = function () { this.btnPlay.src = SHOST + "/images/btn_play.gif"; }.bindAsEventListener(this);
		this.btnPlay.onmouseout = function () { this.btnPlay.src = SHOST + "/images/results/play_big.gif"; }.bindAsEventListener(this);
	},

	play: function (event) {
		if (bc.players.length > 0)
			bc.openVideo(this.jsonObj, bc.currentForegroundPlayer);
		else
			bc.openNewVideo(this.jsonObj);
	},

	play_new: function () {
		bc.openNewVideo(this.jsonObj);
	},

	add_to_favorites: function () {
		Favorites.addVideo(this.jsonObj);
	},
	remove_from_favorites: function () {
		Favorites.removeVideo(this.jsonObj);
		this.container.removeResult(this);
	},

	downloadConverted: function () {
		Converter.downloadConverted(this.jsonObj);
	},

	downloadAsFlv: function () {
		Converter.downloadFLV(this.jsonObj);
	},

	remove: function () {
		this.container.element.removeChild(this.element);
		if (this.element) delete (this.element);
	},

	recommend: function () {
		send_recommendation(this.jsonObj.id, this.jsonObj.title);
	},

	startDragging: function (event) {
		dnd.startDragging(event, this);
		dnd.setImage(this.jsonObj.thumbnail_url);
	},

	hoverResult: function (event) {
		Element.addClassName(this.div, 'hovered');
		//Event.stop(event);
		if (this.hoverResult_theme)
			this.hoverResult_theme(event);
	},

	unhoverResult: function (event) {
		Element.removeClassName(this.div, 'hovered');
		//Event.stop(event);
		if (this.unhoverResult_theme)
			this.unhoverResult_theme(event);
	},
	showHint: function (event) {
		Hint.showDelayed(event, this.jsonObj.title, this.jsonObj.description, this.element);
	},
	hideHint: function () {
		Hint.hide();
	},
	resize: function (width, fontSize) {
		this.element.style.width = width + "px";
		this.element.style.height = (width * this.container.ResultAspectRatio) + "px";
		/*if (arguments.length == 1)
			var fontSize = (this.container.minFontSize + (this.container.maxFontSize - this.container.minFontSize) * (width - this.container.minResultWidth ) / (this.container.maxResultWidth - this.container.minResultWidth));*/
		this.element.style.fontSize = fontSize + "px";
		this.element.style.lineHeight = (fontSize * 1.2) + "px";
		this.elementTitle.style.height = ( 2.4 * fontSize ) + "px";

		if (width < 160)
			this.ratingContainer.style.display = "none";
		else
			this.ratingContainer.style.display = "block";

		if (width < 120)
			this.lengthContainer.style.display = "none";
		else
			this.lengthContainer.style.display = "block";
	}
}

var AdResult = Class.create();
AdResult.prototype = {
	initialize: function (container, jsonObj) {
		this.container =  container;
		this.jsonObj = jsonObj;

		Object.extend(this, TemplatedElement);
		this._buildFromTemplate('template_result_ad');
		this.div = this.element;

		this.thumbnail.src = this.jsonObj.thumbnail;
		this.thumbnail.alt = this.jsonObj.descr;

		if (this.jsonObj.thumbnailBig) {
			this.thumbnailBig.src = this.jsonObj.thumbnailBig;
			this.thumbnailBig.alt = this.jsonObj.descr;
			this.hasBigVersion = true;
		} else {
			this.element.removeChild(this.thumbnailBig);
			this.hasBigVersion = false;
		}

		this.elementDescription.innerHTML = jsonObj.descr;
		this.container.element.appendChild(this.div);
		this.resize(this.container.results_size, this.container.results_font_size);
	},
	open: function () {
		urchinTracker('/ads/clicked/' + this.jsonObj.id);
		new Ajax.Request ('/ad_clicked.php?aid=' + this.jsonObj.id, {method:'post'});
		if (this.jsonObj.onclick_v) {
			openVideoById(this.jsonObj.onclick_v, false);
		} else
			window.open ('http://' + this.jsonObj.onclick_u);
	},
	resize: function (width, fontSize) {
		this.element.style.width = width + "px";
		this.element.style.height = (width * this.container.ResultAspectRatio) + "px";
		/*if (arguments.length == 1)
			var fontSize = (this.container.minFontSize + (this.container.maxFontSize - this.container.minFontSize) * (width - this.container.minResultWidth ) / (this.container.maxResultWidth - this.container.minResultWidth));*/
		this.element.style.fontSize = fontSize + "px";
		this.element.style.lineHeight = (fontSize * 1.2) + "px";
		this.elementDescription.style.height = ( 2.4 * fontSize ) + "px";

		if (this.hasBigVersion) {
			this.thumbnail.style.display = (width < 220?'':'none');
			this.thumbnailBig.style.display = (width >= 220?'':'none');
		}
	},
	remove: function () {
		this.container.element.removeChild(this.element);
		if (this.element)
			delete (this.element);
	}
}

var ResultsContainer = Class.create ();
ResultsContainer.prototype = {
	ResultAspectRatio: 328/290,//323/263,
	minFontSize: 10, maxFontSize: 16,
	minResultWidth: 100, maxResultWidth: 350,
	initialize: function (element, player_chooser) {
		this.element = $(element);
		this.player_chooser = $(player_chooser);

		this.Results = new Array ();
		this.results_cache = new Array ();
		this.results_per_page = 18;

		this.visible_first = 1;
		this.visible_last = this.results_per_page;

		if (onl_results_size)
			this.results_size = onl_results_size;
		else
			this.results_size = parseInt(Cookies.getValue('results_size', '145')); // this is the width of the results css class
		this.results_font_size = (this.minFontSize + (this.maxFontSize - this.minFontSize) * (this.results_size - this.minResultWidth ) / (this.maxResultWidth - this.minResultWidth));
		this.resultsCurrentWidth = this.results_size;
		this.resultsCurrentHeight =this.results_size * this.ResultAspectRatio;
		this.pages_count = 0; // the current_page variable is global
		this.results_count = 0;

		current_page = 0;
		Slider.setValue(this.results_size);
		this.btn_prev_page = $('btn_prev_page');
		this.btn_prev_page.onclick = this.switchToPrevPage.bindAsEventListener(this);
		this.btn_next_page = $('btn_next_page');
		this.btn_next_page.onclick = this.switchToNextPage.bindAsEventListener(this);

		this.onResize_handler = this.fixResultsVisibility.bindAsEventListener(this);
		Event.observe(window, 'resize', this.onResize_handler);
		//this.element.onresize = this.fixResultsVisibility.bindAsEventListener(this);

		this.element_loading = document.createElement('div');
		this.element_loading.className = "div_loading_results";
		this.element_loading.innerHTML = "<img src='" + SHOST + "/images/preloader.gif' alt='preloader'>";
		this.err_element = document.createElement('div');
		this.err_element.className = "div_results_error";

		Event.observe (this.element, "mousewheel", this.onMouseWheel.bindAsEventListener(this));
	},

	addResult: function (jsonObj) {
		if (jsonObj.t == 'v')
			this.Results.push(new Result(this, jsonObj));
		else if (jsonObj.t == 'a')
			this.Results.push(new AdResult(this, jsonObj));
	},
	removeResult: function (result) {
		this.results_count --;
		this.Results = this.Results.without(result);
		this.results_cache = this.results_cache.without(result.jsonObj);
		result.remove();
		this.showResults(this.visible_first); // should be smarter here
	},

	showError: function (err_text) {
		this.clearResults();
		this.err_element.innerHTML = err_text;
		this.element.appendChild(this.err_element);
	},

	clearCache: function () {
		this.results_cache.clear();
	},

	clearResults: function () {
		for (var i = 0; i < this.Results.length; i++ )
			this.Results[i].remove();
		this.Results.clear();
		this.element.innerHTML = '';
	},

	// loadResults is called by the main engine when new search is initiated
	loadResults: function(jsonObj) {
		this.clearResults();
		this.clearCache();
		//this.Results = jsonObj.results;
		if (jsonObj.results.length == 0) {
			this.setNoResults();
			return;
		} else {
			//this.pages_count = jsonObj.pgs;
			this.results_count = jsonObj.total;
		}
		// add the results to the cache...
		if (last_list_by == 'recently_played') { // fix the order of the results
			for (var i = 0; i < jsonObj.results.length; i ++) {
				jsonObj.results[i].ord = i;
				this.results_cache[jsonObj.results[i].ord] = jsonObj.results[i];
			}
		} else
			for (var i = 0; i < jsonObj.results.length; i ++)
				this.results_cache[jsonObj.results[i].ord] = jsonObj.results[i];
		this.lastRequestResultCount = jsonObj.results.length;
		this.showResults(0, this.results_per_page);
	},

	// adds MAX_PER_PAGE more results to cache. Calls the main engine to query search.php
	ExtendCache: function () {
		if (this.results_cache.length < this.results_count) {
			search(Math.floor((this.results_cache.length)/MAX_PER_PAGE) + 1, last_list_by, true, last_search_string, last_related_video_id);
		}
	},

	// called by the main engine when new results for cache request have arrived
	ExtendCache_handler: function (jsonObj) {
		this.extending_cache = false;
		for (var i = 0; i < jsonObj.results.length; i ++) {
			// add the results to the cache...
			this.results_cache[jsonObj.results[i].ord] = jsonObj.results[i];
		}
		this.lastRequestResultCount = jsonObj.results.length;

		this.results_count = jsonObj.total;
		if (this.showResultsWhenCacheArrives != null) {
			this.showResults(this.showResultsWhenCacheArrives.from, this.showResultsWhenCacheArrives.to); // the "to" param is ognored
		} else {
			if (jsonObj.total != this.results_count) {
				var s =(1 + this.visible_first);
				var f = (1 + this.visible_last);
				$('curent_page_info').innerHTML = s + " - "  + f + " (" + formatCommasInt(this.results_count) + ") " ;
			}
		}
	},

	showResults: function (from) {
		// first check if we have these results, else load them in cache
		if (from < 0) from = 0;
		var to = from + 130 - 1;
		if (to > this.results_count) to = this.results_count - 1;
		this.showResultsWhenCacheArrives = null;
		if (to > this.results_cache.length - 1 && this.lastRequestResultCount == MAX_PER_PAGE) {
			this.showResultsWhenCacheArrives = {from:from, to:to};
			this.showLoadingAjax();
			this.ExtendCache();
			return; /// ExtendCache_handler must give back control here when results are ready
		}

		this.clearResults();
		// add the result to the currently displayed
		for (var i = from; i <= to; i ++)
			if (this.results_cache[i])
				this.addResult(this.results_cache[i]);
		this.visible_first = from;
		this.visible_last = to;
		this.fixResultsVisibility();
		// if the user is close to the end of the cache, extend it to bring earlier next results
		if ((this.visible_last >= this.results_cache.length - MAX_PER_PAGE) &&
			(this.results_cache.length < this.results_count) &&
			(this.lastRequestResultCount == MAX_PER_PAGE))
			this.ExtendCache();
		this.fixPageSwitchers();
	},

	resizeResults: function (new_size, sendSaveSettings) {
		if (new_size < 100) return;
		if (new_size > 350) return;
		if (arguments.length < 2) var sendSaveSettings = true;
		this.results_size = new_size;
		this.resultsCurrentWidth = new_size;
		this.resultsCurrentHeight = new_size * this.ResultAspectRatio;

		this.results_font_size = (this.minFontSize + (this.maxFontSize - this.minFontSize) * (new_size - this.minResultWidth ) / (this.maxResultWidth - this.minResultWidth))
		Cookies.setValue('results_size', new_size);
		if (user_name && sendSaveSettings) {
			if (this.saveresultssizeajax) clearTimeout(this.saveresultssizeajax);
			this.saveresultssizeajax = setTimeout('new Ajax.Request("save_settings.php", {method:"post", parameters: "results_size=' + new_size + '"});', 1000);
		}

		for (var i = 0; i < this.Results.length; i ++)
			this.Results[i].resize(new_size, this.results_font_size);
		this.fixResultsVisibility();
	},
	onMouseWheel: function (event) {
		var d = Event.wheelDelta(event);
		if (d == 0) return true;
		if (d > 0)
			this.resizeResults(this.results_size + 20);
		else
			this.resizeResults(this.results_size - 20);
		Slider.setValue(this.results_size);
	},

	fixResultsVisibility: function () { // the parameter is used only by IE6
		if (this.Results.length == 0) return;

		var ew = this.element.offsetWidth;
		var eh = this.element.offsetHeight;

		if (isIE6) {
			eh = $('m_bottom').offsetTop - 93;
		}
		this.element.style.paddingTop = "0px";
		this.element.style.paddingLeft = "0px";
		// calculate the visible_last to match the new size and hide the unnecessary resutls...
		/*if (isIE6) {
			var res_w = this.results_size;
			var res_h = Math.round(this.results_size*164/145);
		} else {
			var res_w = this.Results[0].div.clientWidth + 2 * this.Results[0].div.offsetLeft; // add margins!
			var res_h = this.Results[0].div.clientHeight + 2 * this.Results[0].div.offsetTop; // add margins!
		}*/
		var res_w = this.resultsCurrentWidth + 8;
		var res_h = this.resultsCurrentHeight + 8;
		//alert (ew + " " + eh + "\n" + res_w + " " + res_h);
		var cols = Math.floor(ew / res_w);
		var rows = Math.floor(eh / res_h);

		//if (isIE6) alert ((this.visible_first + rows * cols - 1 ) +  "\n" + (this.results_cache.length - 1));
		this.visible_last = Math.min(this.visible_first + rows * cols - 1, this.results_cache.length - 1);
		this.visible_per_page = rows * cols; // used to calculate the showed results when pressing the prev page button

		for (var i = 0; i <= this.visible_last - this.visible_first; i ++)
			if (this.Results[i]) this.Results[i].div.style.display = 'block';


		for (var i = 1 + this.visible_last - this.visible_first; i < this.Results.length; i ++)
			if (this.Results[i])	this.Results[i].div.style.display = 'none';
		// this should never be needed, I think

		if ((this.visible_last > this.results_cache.length - MAX_PER_PAGE / 2) &&
			(this.results_cache.length < this.results_count))
			this.ExtendCache();
		this.fixPageSwitchers();
		// now fix the padding of the surrounding element
		// recalc rows accoding to the actual number of visible items
		rows = Math.ceil (( 1 + this.visible_last - this.visible_first) / cols);
		var tw = (rows > 1 ? cols : 1 + this.visible_last - this.visible_first) * res_w ;
		var th = rows * res_h;


		var pt = Math.floor((eh - th) / 2);
		var pb = Math.floor((ew - tw) / 2);

		if (pt > -1 && !isIE6)
			this.element.style.paddingTop = pt + "px" ;
		else
			this.element.style.paddingTop = "0px" ;
		if (pb > -1)
			this.element.style.paddingLeft = pb + "px" ;
		else
			this.element.style.paddingLeft = "0px" ;
		var s =(1 + this.visible_first);
		var f = (1 + this.visible_last);
		$('curent_page_info').innerHTML = s + " - "  + f + " (" + formatCommasInt(this.results_count) + ") " ;
	},

	fixPageSwitchers: function () {
		if (this.visible_first > 0)
			this.btn_prev_page.style.display = ""
		else
			this.btn_prev_page.style.display = "none";
		if (this.visible_last < this.results_count - 1)
			this.btn_next_page.style.display = ""
		else
			this.btn_next_page.style.display = "none";
	},

	showLoadingAjax: function () {
		this.clearResults();
		this.element.appendChild(this.element_loading);
	},

	setNoResults: function () {
		this.clearResults();
		var t = '';
		if (this.showFavorites) {
			t = 'You have no videos here yet!<br />Would you like us to show you <a href="/faq.php#66" target="_blank">how to add some favorites</a>?';
		} else if (last_list_by == '' || last_list_by == 'by_tag' || last_list_by == 'by_category_and_tag')
			t = 'Your search for "' +
				last_search_string + '" did not match any videos!<br /><br />' +
				'<div class="l">Suggestions:</div>' +
				'<ul><li>Make sure all words are spelled correctly</li>' +
				'<li>Try different keywords</li>' +
				'<li>Try more general keywords</li>' +
				'<li>Try fewer keywords</li></ul>';
		else {
			t = 'Your search did not match any videos!';
		}
		this.err_element.innerHTML = t;
		this.element.appendChild(this.err_element);
		this.pages_count = 0;
		this.results_count = 0;
	},

	switchToPrevPage: function () {
		this.showResults(this.visible_first - this.visible_per_page);
	},

	switchToNextPage: function () {
		this.showResults(this.visible_last + 1);
	},

	getResultsJson: function (count) {
		var res = [];
		for (var i = 0; i < count; i ++) {
			res[i] = this.Results[i].jsonObj;
		}
		return res;
	}
}

function choosePlayerById(id) {
	rc.choosePlayerById(id);
}
function redrawIEResults () {
	rc.fixResultsVisibility();
}
