﻿var StarList = Class.create();
Object.extend(StarList.prototype, Enumerable);
Object.extend(StarList.prototype, {
	_collection: [],
	_selectedIndex: -1,
	_previousIndex: -1,

	initialize: function(elStarList, options){
		this.elStarList = $(elStarList);
		if(!(Object.isElement(this.elStarList))){return;}
		this._collection = this.elStarList.childElements();
		this._collection.first().addClassName('first');
		this._collection.last().addClassName('last');

		this.options = Object.extend({
			disabled: false,
			canReRate: false
		}, options || {});
		
		this.isDisabled = this.options.disabled;
		// deal with previous value/rating
		if(this.options.previousValue){
			var elLi = this.findByValue(this.options.previousValue);
			this._previousIndex = this.getItemIndex(elLi);
			this.setSelectedByIndex(this._previousIndex);
		}
		
		if(this.isDisabled == false){
			this.enable();
		}else{
			this.disable();
		}
		
	},
	
	enable: function(){
		this.isDisabled = false;
		this.elStarList.observe('mouseover', this.__listOver.bindAsEventListener(this));
		this.elStarList.observe('mouseout', this.__listOut.bindAsEventListener(this));
		this.elStarList.observe('click', this.__listClick.bindAsEventListener(this));
		this.elStarList.removeClassName('disabled');
	},
	
	disable: function(){
		this.isDisabled = true;
		this.elStarList.stopObserving('mouseover');
		this.elStarList.stopObserving('mouseout');
		this.elStarList.stopObserving('click');
		this.elStarList.addClassName('disabled');
		this.elStarList.removeClassName('over');
	},
	
	rate: function(elLi){
		var index = this.getItemIndex(elLi);
		//this.setSelectedByIndex(index); // selected should be set in callback
		var rating = this.getItemValue(elLi);
		this.elStarList.fire('starlist:rated', {"item": elLi, "value":  parseInt(rating), "index": index, "instance": this})
	},
	
	hasRated: function(){
		return(this._previousIndex > -1)
	},
	
	setStars: function(itemIndex){
		//console.log('setStars', itemIndex)
		this.each(function(elLi, index){
			if(index <= itemIndex){
				elLi.addClassName('full');
			}
			else{
				elLi.removeClassName('full');
			}
		});
	},
		
	_each: function(iterator){
		return this._collection._each(iterator);
	},

	getItemIndex: function(elLi){
		return this._collection.indexOf(elLi);
	},
	
	getItem: function(index){
		return this._collection[index];
	},

	getItemValue: function(elLi){
		return elLi.innerHTML.stripTags().strip();
	},
	
	findByValue: function(value){
		return this._collection.find(function(item){
			return item.innerHTML.stripTags().strip() == value;
		});
	},
	
	getSelectedItem: function(){
		return this._collection[this._selectedIndex];
	},
	
	getSelectedValue: function(){
		return this.getItemValue(this._selectedIndex);
	},	
	
	setSelectedByIndex: function(index){
		// store previous selection if it applicable
		if(this._selectedIndex > -1){
			this._previousIndex = this._selectedIndex;
		}
		
		this._selectedIndex = index;
		this.setStars(index);
	},
	
	setSelectedByValue: function(value){
		var el = this.findByValue(value);
		if(Object.isElement(el)){
			var index = this.getItemIndex(el);
			this.setSelectedByIndex(index);			
		}
	},

	
	// Event handlers
	__listOver: function(e){
		//console.log('listOver fired.');
		var el = e.element();
		
		if(el == this.elStarList){
			return; // in the margins
		} else{
			el = Event.findElement(e,'li');
			this.setStars(this.getItemIndex(el));
			// e.relatedTarget is the element that the mouse left.
			if(e.relatedTarget && !e.relatedTarget.descendantOf(this.elStarList)){
				this.elStarList.addClassName('over');
				this.elStarList.fire('starlist:over', {instance:this});
			}
		}
	},
	
	__listOut: function(e){
		this.setStars(this._selectedIndex);
		var el = e.element();
		// e.relatedTarget is the element where the mouse went.
		if(e.relatedTarget && !e.relatedTarget.descendantOf(this.elStarList) && el != this.elStarList){
			this.elStarList.removeClassName('over');
			this.elStarList.fire('starlist:out', {instance:this});
		}
	},
	
	__listClick: function(e){
		//console.log('__listClick fired.');
		e.stop();
		var el = e.element();
		if (el == this.elStarList) {
			return; // in the margins
		}
		else {
			el = Event.findElement(e, 'li');
			this.rate(el);
		}
	}
});
/*
var StarRating = Class.create(StarList, {
	initialize: function($super, elStarList, options){
		$super(elStarList, options);
		
		this.elStarList.observe('starlist:over', this.__starListOver.bindAsEventListener(this));
		this.elStarList.observe('starlist:out', this.__starListOut.bindAsEventListener(this));
		this.elStarList.observe('starlist:rated', this.__starListRated.bindAsEventListener(this));
		
		// May not need to deal with prompt element or copy.
		this.promptCopy = Object.extend({
			read: "Rate this item",
			rate: "Click a rating",
			rerate: "Edit my rating"
		}, this.options.prompts || {});
		
		if(Object.isElement(options.elPromptTarget)){
			this.elPromptTarget = options.elPromptTarget;
		} else{
			this.elPromptTarget = new Element('div', {'class': 'rating-prompts'});
			this.elStarList.insert({before: this.elPromptTarget});
		}
		
		this.elPromptTarget.update(this.promptCopy.read);
		//this.spinner = new Element('div', {id: containerID + '_spinner', 'class': 'util_flyout_spinner', title: 'Loading...', style: 'opacity: .50'}); || false;
	},
	__starListOver: function(ce){
		var prompt = (this._previousIndex > -1) ? this.promptCopy.rerate : this.promptCopy.rate;
		this.elPromptTarget.update(prompt);
	},
	
	__starListOut: function(ce){
		this.elPromptTarget.update(this.promptCopy.read);
	},
	
	__starListRated: function(ce){
		// TODO: 
		// * call static web method or service with user rating		
		//lnkRatePhoto(ce.memo)
		// * optionally show a spinner
		
		console.log(ce.memo);
		this.setSelectedByIndex(ce.memo.index); //this should be done after xhr
		
	},
	
	__xhrAfter: function(transport){
		console.log('vote received');
		
		// TODO:
		// * this.setSelectedByIndex(ce.memo.index); //set selected
		// * update total count
		// * optionally hide spinner
		if(this.options.canReRate == false){
			this.disable();
		}
	}
	
});
*/
/*Using Postback*/
var StarRating = Class.create(StarList, {
	initialize: function($super, elStarList, hdnRatingID, btnRateID, options){
		this.hdnRating = $(hdnRatingID);
		this.btnRate = $(btnRateID);
		// check if there's a previous value in the hidden field, if so set previousValue
		if(this.hdnRating.empty() == true){
			options.previousValue = parseInt(this.hdnRating.value);
		}
		
		$super(elStarList, options);
		
		this.elStarList.observe('starlist:over', this.__starListOver.bindAsEventListener(this));
		this.elStarList.observe('starlist:out', this.__starListOut.bindAsEventListener(this));
		this.elStarList.observe('starlist:rated', this.__starListRated.bindAsEventListener(this));
		
		// May not need to deal with prompt element or copy.
		this.promptCopy = Object.extend({
			rate: "Rate this image.",
			rateOver: "Rate this image.", 
			rerate: "Edit your rating", 
			rerateOver: "Edit your rating"
		}, this.options.prompts || {});
		
		if(Object.isElement(options.elPromptTarget)){
			this.elPromptTarget = options.elPromptTarget;
		} else{
			this.elPromptTarget = new Element('div', {'class': 'rating-prompts'});
			this.elStarList.insert({before: this.elPromptTarget});
		}
		var prompt = (this.hasRated() == true) ? this.promptCopy.rerate : this.promptCopy.rate;
		this.elPromptTarget.update(prompt);
	},

	__starListOver: function(ce){
		var prompt = (this.hasRated() == true) ? this.promptCopy.rerateOver : this.promptCopy.rateOver;
		this.elPromptTarget.update(prompt);
	},
	
	__starListOut: function(ce){
		var prompt = (this.hasRated() == true) ? this.promptCopy.rerate : this.promptCopy.rate;
		this.elPromptTarget.update(prompt);
	},
	
	__starListRated: function(ce){
		// Set the hidden field and click hidden rate button
		this.hdnRating.value = ce.memo.value;
		this.btnRate.click();
		//console.log(ce.memo);
		this.setSelectedByIndex(ce.memo.index);
		//this.elPromptTarget.update(this.promptCopy.rerateOver);
	}
	
});

/*
 TournamentScoring is similar to StarRating, except it doesn't handle the prompts (e.g. "Rate this item");
*/
var TournamentScoring = Class.create(StarList, {
	initialize: function($super, elStarList, hdnRatingID, btnRateID, options){
		this.hdnRating = $(hdnRatingID);
		this.btnRate = $(btnRateID);
		// check if there's a previous value in the hidden field, if so set previousValue
		if(this.hdnRating.empty() == true){
			options.previousValue = parseInt(this.hdnRating.value);
		}
		
		$super(elStarList, options);
		
		this.elStarList.observe('starlist:rated', this.__starListRated.bindAsEventListener(this));
	},
		
	__starListRated: function(ce){
		// Set the hidden field and click hidden rate button
		this.hdnRating.value = ce.memo.value;
		this.btnRate.click();
		//console.log(ce.memo);
		this.setSelectedByIndex(ce.memo.index);
		//this.elPromptTarget.update(this.promptCopy.rerateOver);
	}
	
});



