/**
 * @class HD.community.Video
 * @description The purpose of community.Video is to provide a video object. 
 * 				Registered as hd_video.
 * @constructor
 * @extends HD.Widget
 * @see HD.community.Video.hooks
 * @see HD.community.Video.templates
 * @see HD.community.Media.hooks
 * @property {object} 	config
 *                    	The configuration for the widget.
 * @property {object} 	[config.hooks=HD.community.Video.hooks]
 *                 		Customized subset of hooks (merged with the defaults).
 * @property {object} 	[config.templates=HD.community.Video.templates]
 *                 		Customized subset of templates (merged with the defaults).
 * @property {object}	data
 * 						Media response
 * @property {array)	ratings
 * 						Ratings array                
 */
HD.community.Video = function(video) {
	this.data = video;
	this.ratings = [];
};

/**
 * The collection of default templates.
 * @fieldOf HD.community.Video
 */
HD.community.Video.templates = {
		
	/**
	 * Label for the video author
	 * @memberOf HD.community.Video
	 */	
	authorLabel       : "Submitted by: ",
	
	/**
	 * Label for the video date
	 * @memberOf HD.community.Video
	 */	
	dateLabel         : "",
	
	/**
	 * Label for the video tags
	 * @memberOf HD.community.Video
	 */	
	tagsLabel         : "Tags: ",
	
	/**
	 * Label for the video category
	 * @memberOf HD.community.Video
	 */	
	categoryLabel     : "Category: ",
	
	/**
	 * Video more text
	 * @memberOf HD.community.Video
	 */	
	moreText          : "Watch Video",
	
	/**
	 * Blog first comment text
	 * @memberOf HD.community.Video
	 */	
	commentsTextFirst : "Comments ({number})",
	
	/**
	 * Video comments text
	 * @memberOf HD.community.Video
	 */	
	commentsText      : "Comments (${number})",
	
	/**
	 * Label for the next video link
	 * @memberOf HD.community.Video
	 */	
	nextLabel         : "Next",
	
	/**
	 * Label for the previous video link
	 * @memberOf HD.community.Video
	 */	
	previousLabel     : "Previous",
	
	/**
	 * Video average votes text
	 * @memberOf HD.community.Video
	 */	
	averageVotesText  : "(Average of ${num_of_votes}&nbsp;ratings:&nbsp;${text_rating}&nbsp;stars)",
	
	/**
	 * Video send to a friend text
	 * @memberOf HD.community.Video
	 */	
	emailText         : "Send to a friend",
	
	/**
	 * @constant
	 * @return {string} Author label for the widget: authorLabel
	 * @memberOf HD.community.Video
	 */
	getAuthorLabel : function(){
		return this.authorLabel;
	},
	
	/**
	 * @constant
	 * @return {string} Date label for the widget: dateLabel
	 * @memberOf HD.community.Video
	 */
	getDateLabel : function(){
		return this.dateLabel;
	},
	
	/**
	 * @constant
	 * @return {string} Tags label for the widget: tagsLabel
	 * @memberOf HD.community.Video
	 */
	getTagsLabel : function(){
		return this.tagsLabel;
	},
	
	/**
	 * @constant
	 * @return {string} Category label for the widget: categoryLabel
	 * @memberOf HD.community.Video
	 */
	getCategoryLabel : function(){
		return this.categoryLabel;
	},
	
	/**
	 * @constant
	 * @return {string} More text for the widget: moreText
	 * @memberOf HD.community.Video
	 */
	getMoreText : function(){
		return this.moreText;
	},
	
	/**
	 * @constant
	 * @return {string} Comments text for the widget: commentsText
	 * @memberOf HD.community.Video
	 */
	getCommentsText : function(numOfComments) {
		var text = this.commentsTextFirst.replace(/\{number\}/, numOfComments);
		if(numOfComments != null && numOfComments > 0) {
			text = this.commentsText.replace(/\{number\}/, numOfComments);
		}
		return text;
	},
	
	/**
	 * @constant
	 * @return {string} Next label for the widget: nextLabel
	 * @memberOf HD.community.Video
	 */
	getNextLabel : function(){
		return this.nextLabel;
	},
	
	/**
	 * @constant
	 * @return {string} Previous label for the widget: previousLabel
	 * @memberOf HD.community.Video
	 */
	getPreviousLabel : function(){
		return this.previousLabel;
	},
	
	/**
	 * @constant
	 * @return {string} Average votes text for the widget: averageVotesText
	 * @memberOf HD.community.Video
	 */
	getAverageVotesText : function(numOfVotes, textRating) {
		return this.averageVotesText.replace(/\$\{num_of_votes\}/, numOfVotes).replace(/\$\{text_rating\}/, textRating);
	},
	
	/**
	 * @constant
	 * @return {string} Send to a friend text for the widget: emailText
	 * @memberOf HD.community.Video
	 */
	getEmailText : function() {
		return this.emailText;
	},
	
	/**
	 * @constant
	 * @return {string} Main template for the widget
	 * @memberOf HD.community.Video
	 */
	getHtml : function() {
		return this.html;
	},
	
	/**
	 * @constant
	 * @return {string} Votes class text for the widget
	 * @memberOf HD.community.Blog
	 */
	getVotesText : function(){
		return HD.util.StarRating.CSS_CLASSES.NUM_OF_VOTES + ' ' + HD.community.Video.hooks.MEDIA_VOTES;
	},
	
	/**
	 * @constant
	 * @return {string} Ratings class text for the widget
	 * @memberOf HD.community.Blog
	 */
	getRatingText : function(){
		return HD.util.StarRating.CSS_CLASSES.TEXT_RATING + ' ' + HD.community.Video.hooks.MEDIA_RATING_TEXT;
	},
	
	/** 
	 * Main template for the widget
	 * @memberOf HD.community.Video
	 * @type jst_template
	 */	
	html :  '\
		<div class="${classes.ITEM} ${classes.VIDEO}{if !video.previous} ${classes.FIRST}{/if}{if !video.next} ${classes.LAST}{/if} ${hooks.MEDIA_ITEM}">\
			<div class="${classes.SMALL_THUMB_WRAPPER}">\
				<div class="${classes.SMALL_THUMB} ${hooks.MEDIA_THUMB}" style="background: transparent url(${video.thumbUrl}) no-repeat 50% 50%;">\
					<div class="${classes.THUMB_OVERLAY}"></div>\
				</div>\
			</div>\
			<div class="${classes.LARGE_THUMB_WRAPPER}">\
				<div class="${classes.LARGE_THUMB} ${hooks.MEDIA_THUMB_LG}"></div>\
			</div>\
			<div class="${classes.LEFT}">\
				<div class="${classes.TITLE} ${hooks.MEDIA_TITLE}">${video.title|ellipse:config.titleLength || video.title.length}</div>\
				<div class="${classes.CATEGORIES}">\
				{if video.category}\
					<div class="${classes.LABEL}">${templates.getCategoryLabel()}</div>\
					<div class="${classes.VALUE}"><a class="${classes.CATEGORY} ${hooks.MEDIA_CATEGORY}" href="javascript:void(0)">${video.category}</a></div>\
				{/if}\
				</div>\
				<div class="${classes.TAG_LIST}">\
				{if hasTags}\
					<div class="${classes.LABEL}">${templates.getTagsLabel()}</div>\
					<div class="${classes.VALUE}">\
					{for tag in video.tags}{if tag_index > 0}${", "}{/if}<a class="${classes.TAG} ${hooks.MEDIA_TAG}" href="javascript:void(0)">${tag}</a>{/for}\
					</div>\
				{/if}\
				</div>\
				<div class="${classes.AUTHOR} ${hooks.MEDIA_AUTHOR}">\
				{if !video.hiddenAuthor}\
					<div class="${classes.LABEL}">${templates.getAuthorLabel()}</div>\
					<div class="${classes.VALUE}">${video.author}</div>\
				{/if}\
				</div>\
				<div class="${classes.DATE}">\
					<div class="${classes.LABEL}">${templates.getDateLabel()}</div>\
					<div class="${classes.VALUE}">${video.uploadedDate|date}</div>\
				</div>\
				<div class="${classes.RATING}">\
					<div class="${ratingClasses.AVERAGE_RATING} ${hooks.MEDIA_RATING_AVG}">\
						<div class="${ratingClasses.STAR_RATING} ${hooks.MEDIA_RATING_STAR}"></div>\
						<div class="${classes.WRAPPER}">\
							(<div class="${ratingClasses.NUM_OF_VOTES} ${hooks.MEDIA_VOTES}"></div>)\
						</div>\
					</div>\
					<div class="${ratingClasses.MY_RATING} ${hooks.MEDIA_RATING_MY}">\
						<div class="${ratingClasses.CAPTION} ${hooks.MEDIA_CAPTION}"></div> \
						<div class="${ratingClasses.STAR_RATING} ${hooks.MEDIA_RATING_STAR}"></div>\
						<br/><div class="${classes.RATING}Wrapper">\
							${templates.getAverageVotesText(\'<div class="\'+templates.getVotesText()+\'"></div>\',\'<div class="\'+templates.getRatingText()+\'"></div>\')}\
						</div>\
					</div>\
				</div>\
			</div>\
			<div class="${classes.RIGHT}">\
				<div class="${classes.NAVIGATION}">\
					<div class="${classes.PREVIOUS} ${hooks.MEDIA_PREVIOUS}">${templates.getPreviousLabel()}</div>\
					<div class="${classes.NEXT} ${hooks.MEDIA_NEXT}">${templates.getNextLabel()}</div>\
				</div>\
				<a class="${classes.COMMENTS}Button ${hooks.MEDIA_COMMENTS_BTN}" id="${commentsButtonId}">${templates.getCommentsText(video.numberOfComments)}</a>\
				<div class="${classes.EMAIL}">${templates.getEmailText()}</div>\
			</div>\
			<div class="${classes.DESCRIPTION}">\
				<div>${video.description}</div>\
			</div>\
			{if config.embedShare}\
				${shareWidget|html}\
			{/if}\
			{if config.embedSendFriend}\
				${sendFriendWidget|html}\
			{/if}\
		</div>'
};

(function() {
	
	/**
	 * The collection of hooks
	 */
	HD.community.Video.hooks = HD.clone(HD.community.Media.hooks);
})();

HD.community.Video.prototype = {
	
	/**
	 * Renders the HTML for the widget based on dynamic data.
	 * @param {object} [data]
	 *                 Event data from the render phase
	 * @returns {string} HTML for the widget
	 */
	getHtml : function(config) {
		var video = this.data;
		if(video == null) {
			return "";
		}
		
		// Load templates from the dynamic config.
		this.loadTemplates(HD.community.Video.templates, HD.community.Video.hooks, { config: config, templates: 'videoTemplates', hooks: 'videoHooks'});
		
		this.commentsButtonId = HD.util.Common.generateElementId();
		
		// Embed share/send friend widgets.
		if (config.embedShare) {
			this.shareWidget = new HD.ShareWidget(HD.merge(config.shareConfig, { embedMode: true }));
		}
		if (config.embedSendFriend) {
			this.sendFriendWidget = new HD.SendFriendWidget(HD.merge(config.sendFriendConfig, { embedMode: true }));
		}
		
		return this.processTemplate(this.config.templates.getHtml(), {
			video            : video,
			config           : config,
			shareWidget      : this.shareWidget || null,
			sendFriendWidget : this.sendFriendWidget || null,
			commentsButtonId : this.commentsButtonId,
			hasTags          : video.tags && video.tags.length > 0,
			ratingClasses    : HD.util.StarRating.CSS_CLASSES,
			_MODIFIERS       : {
				html         : function(widget) { return widget.getHtml(video); }
			}
		});
	},
	
	/**
	 * Removes tooltip
	 */
	destroy : function() {
		if (this.tooltip) {
			this.tooltip.destroy();
			delete this.tooltip;
		}
	},

	/**
	 * Sets event listener for the widget.
	 * @param {HTMLElement} videoEl
	 *                 		Container for the video display
	 * @param {object} 		widget
	 * 						Widget object calling the video
	 */
    setListener : function(videoEl, widget) {
    	var video = this.data;
		if(video == null) {
			return "";
		}
		
		var classes = HD.CSS_CLASSES;
		var ratingClasses = HD.util.StarRating.CSS_CLASSES;
		
		var config = widget.config;
		
		// Decide whether the entire widget is clickable or just the thumb
		var isWholeElClickable = config.type.match(/^(hd_gallery_widget|hd_carousel_widget)$/);
		
		var smallThumbEl = HD.getByClass(this.config.hooks.MEDIA_THUMB, '*', videoEl)[0];
		
		if(isWholeElClickable) {
			videoEl.onclick = function() {
				widget.notifyObservers.call(widget, "itemSelected", video);
				widget.model.setActiveItem.call(widget.model, video);
			}; 
		} else if (smallThumbEl){
			smallThumbEl.onclick = function() {
				widget.notifyObservers.call(widget, "itemSelected", video);
				widget.model.setActiveItem.call(widget.model, video);
			}; 
		}
		
		// TODO abstract tooltip into an HD method
		if(config.isShowPopups) {
			this.tooltip = new YAHOO.widget.Tooltip(HD.util.Common.generateElementId(), 
					{ context:smallThumbEl, 
					  text:'<div class="' + HD.CSS_CLASSES.TOOL_TIP + '">' + video.description.substring(0,200) + '</div>',
					  autodismissdelay:60000}); // show tooltip for up to 1 minute
		}
		
		// setup video
		var largeThumbEl = HD.getByClass(this.config.hooks.MEDIA_THUMB_LG, '*', videoEl)[0];
		if (largeThumbEl){
			var player = new HD.util.Player({
				parent : largeThumbEl,
				width: config.playerWidth || 400,
				height: config.playerHeight || 300,
				parentWidget : this,
				templates : config.playerTemplates || {},
				hooks     : config.playerHooks || {}
			});
			
			//var videoUrl = "http://media2.kickapps.com/videos/" + video.mediaId + ".flv";
			var videoUrl = video.viewUrl;
			
			player.view.render({
				videoUrl : videoUrl,
				thumbUrl : video.largeThumbUrl || video.thumbUrl,
				media : video
			});
		}
		
		// Update the comments
		var cb = this;
		widget.model.addObserver({
			update : function(eventName, eventData) {
				if(eventName == "submitComment_Finish" || eventName == "getComments_Finish") {
					if(eventData.mediaId == video.mediaId) {
						cb.data = eventData;
						var buttonEl = HD.get(cb.commentsButtonId);
						if(buttonEl != null) {
							buttonEl.innerHTML = HD.community.Video.templates.getCommentsText(eventData.numberOfComments);
						}
					}
				}
			}
		});
		
		// Attach category clicked events
		if (!!video.category) {
			var catEl = HD.getByClass(this.config.hooks.MEDIA_CATEGORY, '*', videoEl);
			if (catEl[0]) {
				catEl[0].onclick = function() {
					widget.model.setCategories([video.category]);
				};
			}
		}

		// Attach tag clicked events
		if (video.tags && video.tags.length > 0) {
			var tagEls = HD.getByClass(this.config.hooks.MEDIA_TAG, '*', videoEl);
			for (var i = 0, len = tagEls.length; i < len; i++) {
				(function() {
					var tag = video.tags[i];
					tagEls[i].onclick = function() {
						widget.model.setTags([tag]);
					};
				})();
			}
		}
		
    	/////////// RATING ////////////////
    	var myRatingEl = HD.getByClass(this.config.hooks.MEDIA_RATING_MY, '*', videoEl)[0] || null;
    	var avgRatingEl = HD.getByClass(this.config.hooks.MEDIA_RATING_AVG, '*', videoEl)[0] || null;
    	var ratingObserver = {
    		update : function(eventName, eventData) {
    			widget.model.rateMedia.call(widget.model, video.mediaId, video.contentType, eventData);
    		}
    	};
		var isRated = video.currentUserRating > 0;
		var myRating = null;
		if(isRated) {
			myRating = parseInt(video.currentUserRating);
		}
		
		if (avgRatingEl) {
			var captionEl = HD.getByClass(this.config.hooks.MEDIA_CAPTION, '*', avgRatingEl)[0] || null;
			var starRatingEl = HD.getByClass(this.config.hooks.MEDIA_RATING_STAR, '*', avgRatingEl)[0] || null;
			var textRatingEl = HD.getByClass(this.config.hooks.MEDIA_RATING_TEXT, '*', avgRatingEl)[0] || null;
			var numOfVotesEl = HD.getByClass(this.config.hooks.MEDIA_VOTES, '*', avgRatingEl)[0] || null;
			
			var staticRating = new HD.util.StarRating({
				// elements to render data in
				captionParent : captionEl,
				textRatingParent : textRatingEl,
				starRatingParent : starRatingEl,
				numOfVotesParent : numOfVotesEl,
		
				// data values
				numOfVotes : video.numberOfVotes,
				averageRating : video.rating,
	    		isStatic : true,
	    		itemId : video.mediaId,
	    		myRating : myRating,
	    		isRated : isRated,
   		
	    		// config options
	    		numOfDecimals : 1,
	    		requiresLogin : config.requiresRatingLogin,
				showRatingHalves : config.showRatingHalves || false,
	    		showYourRatingText : config.showYourRatingText || false
	    	});
			this.ratings.push(staticRating);
		}
		
		if (myRatingEl) {
			var captionEl = HD.getByClass(this.config.hooks.MEDIA_CAPTION, '*', myRatingEl)[0] || null;
			var starRatingEl = HD.getByClass(this.config.hooks.MEDIA_RATING_STAR, '*', myRatingEl)[0] || null;
			var textRatingEl = HD.getByClass(this.config.hooks.MEDIA_RATING_TEXT, '*', myRatingEl)[0] || null;
			var numOfVotesEl = HD.getByClass(this.config.hooks.MEDIA_VOTES, '*', myRatingEl)[0] || null;
			
			var dynamicRating = new HD.util.StarRating({
				// elements to render data in
				captionParent : captionEl,
				textRatingParent : textRatingEl,
				starRatingParent : starRatingEl,
				numOfVotesParent : numOfVotesEl,
		
				// data values
				numOfVotes : video.numberOfVotes,
				averageRating : video.rating,
	    		isStatic : false,
	    		itemId : video.mediaId,
	    		myRating : myRating,
	    		isRated : isRated,
   		
	    		// config options
	    		numOfDecimals : 1,
	    		requiresLogin : config.requiresRatingLogin,
				showRatingHalves : config.showRatingHalves || false,
	    		showYourRatingText : config.showYourRatingText || false
	    	});
			this.ratings.push(dynamicRating);
			dynamicRating.addObserver(ratingObserver);
		}

		widget.model.addObserver({
			update : function(eventName, eventData) {
				if(eventName == "rateMedia_Finish") {
					if(eventData.mediaId == video.mediaId) {
						video.numberOfVotes = eventData.numberOfVotes;
						video.rating = eventData.rating;
						
						cb.updateRatingWidgets.call(cb, eventData);
					}
				}
			}
		});
		
		
		var model = widget.model;
		
		var previousEl = HD.getByClass(this.config.hooks.MEDIA_PREVIOUS, '*', videoEl)[0];
		var nextEl = HD.getByClass(this.config.hooks.MEDIA_NEXT, '*', videoEl)[0];
		if(previousEl){
			if(model.hasPreviousItem()) {
				previousEl.onclick = function() {
					widget.view.notifyObservers.call(widget.view, "itemChange_Start", video);
					model.getPreviousItem.call(model);
				};
			} else {
				HD.addClass(previousEl, classes.HIDDEN);
			}
		}
		
		if(nextEl){
			if(model.hasNextItem()) {
				nextEl.onclick = function() {
					widget.view.notifyObservers.call(widget.view, "itemChange_Start", video);
					model.getNextItem.call(model);
				};
			} else {
				HD.addClass(nextEl, classes.HIDDEN);
			}
		}
		
		var commentButton = HD.get(cb.commentsButtonId);
		if (commentButton){
			commentButton.onclick = function() {
				var commentsEl = HD.get("commentsDiv");
				if(commentsEl != null) {
					HD.util.Common.scrollTo(commentsEl);
				}
			};
		}
		
		// Update share/send friend widgets.
		if (widget.config.embedShare && this.shareWidget) {
			this.shareWidget.config.parent = videoEl;
			this.shareWidget.setListeners(video);
		}
		if (widget.config.embedSendFriend && this.sendFriendWidget) {
			this.sendFriendWidget.config.parent = videoEl;
			this.sendFriendWidget.setListeners(video);
		}
    }
};

HD.extend(HD.community.Video, [HD.community.Media]);

HD.register('hd_video', 'HD.community.Video', {version: "1.0", build: "1"});