/**
 * @class HD.community.Blog
 * @description The purpose of community.Blog is to provide a blog object. 
 * 				Registered as hd_blog.
 * @constructor
 * @extends HD.Widget
 * @see HD.community.Blog.hooks
 * @see HD.community.Blog.templates
 * @see HD.community.Media.hooks
 * @property {object} 	config
 *                    	The configuration for the widget.
 * @property {object} 	[config.hooks=HD.community.Blog.hooks]
 *                 		Customized subset of hooks (merged with the defaults).
 * @property {object} 	[config.templates=HD.community.Blog.templates]
 *                 		Customized subset of templates (merged with the defaults).
 * @property {object}	data
 * 						Media response
 * @property {array)	ratings
 * 						Ratings array                
 */
HD.community.Blog = function(blog) {
	this.data = blog;
	this.ratings = [];
};

/**
 * The collection of default templates.
 * @fieldOf HD.community.Blog
 */
HD.community.Blog.templates = {
	
	/**
	 * Label for the blog author
	 * @memberOf HD.community.Blog
	 */	
	authorLabel       : "By ",
	
	/**
	 * Label for the blog date
	 * @memberOf HD.community.Blog
	 */	
	dateLabel         : "Submitted ",
	
	/**
	 * Label for the blog tags
	 * @memberOf HD.community.Blog
	 */	
	tagsLabel         : "Tags: ",
	
	/**
	 * Label for the blog category
	 * @memberOf HD.community.Blog
	 */	
	categoryLabel     : "Category: ",
	
	/**
	 * Blog more link text
	 * @memberOf HD.community.Blog
	 */	
	moreText          : "More",
	
	/**
	 * Blog first comment text
	 * @memberOf HD.community.Blog
	 */	
	commentsTextFirst : "Add the first comment",
	
	/**
	 * Blog commments text
	 * @memberOf HD.community.Blog
	 */	
	commentsText      : "Comments ({number})",
	
	/**
	 * Blog back to top text
	 * @memberOf HD.community.Blog
	 */	
	toTopText         : "Back to top",
	
	/**
	 * Label for the next blog link
	 * @memberOf HD.community.Blog
	 */	
	nextLabel         : "Next",
	
	/**
	 * Label for the previous blog link
	 * @memberOf HD.community.Blog
	 */	
	previousLabel     : "Previous",
	
	/**
	 * Blog average votes text
	 * @memberOf HD.community.Blog
	 */	
	averageVotesText  : "Average of ${num_of_votes}&nbsp;ratings:&nbsp;${text_rating}&nbsp;stars",
	
	/**
	 * Blog send to friend text
	 * @memberOf HD.community.Blog
	 */	
	emailText         : "Send to a friend",
	
	/**
	 * @constant
	 * @return {string} Author label for the widget: authorLabel
	 * @memberOf HD.community.Blog
	 */
	getAuthorLabel : function(){
		return this.authorLabel;
	},
	
	/**
	 * @constant
	 * @return {string} Date label for the widget: dateLabel
	 * @memberOf HD.community.Blog
	 */
	getDateLabel : function(){
		return this.dateLabel;
	},
	
	/**
	 * @constant
	 * @return {string} Tags label for the widget: tagsLabel
	 * @memberOf HD.community.Blog
	 */
	getTagsLabel : function(){
		return this.tagsLabel;
	},
	
	/**
	 * @constant
	 * @return {string} Category label for the widget: categoryLabel
	 * @memberOf HD.community.Blog
	 */
	getCategoryLabel : function(){
		return this.categoryLabel;
	},
	
	/**
	 * @constant
	 * @return {string} More text for the widget: moreText
	 * @memberOf HD.community.Blog
	 */
	getMoreText : function(){
		return this.moreText;
	},
	
	/**
	 * @constant
	 * @return {string} Next label for the widget: nextLabel
	 * @memberOf HD.community.Blog
	 */
	getNextLabel : function(){
		return this.nextLabel;
	},
	
	/**
	 * @constant
	 * @return {string} Previous label for the widget: previousLabel
	 * @memberOf HD.community.Blog
	 */
	getPreviousLabel : function(){
		return this.previousLabel;
	},
	
	/**
	 * Returns the text for blog comments
	 * @param {number} 	numOfComments
	 * 					Number of comments for the blog
	 * @return {string} Comments text for the widget
	 * @memberOf HD.community.Blog
	 */
	getCommentsText : function(numOfComments) {
		var text = this.commentsTextFirst;
		if(numOfComments != null && numOfComments > 0) {
			text = this.commentsText.replace(/\{number\}/, numOfComments);
		}
		return text;
	},
	
	/**
	 * @constant
	 * @return {string} Back to top text for the widget: toTopText
	 * @memberOf HD.community.Blog
	 */
	getToTopText : function(){
		return this.toTopText;
	},
	
	/**
	 * Returns the text for average votes
	 * @param {number} 	numOfVotes
	 * 					Number of votes cast for the blog
	 * @param {number} 	textRating
	 * 					Average rating for the blog
	 * @return {string} Average votes text for the widget
	 * @memberOf HD.community.Blog
	 */
	getAverageVotesText : function(numOfVotes, textRating) {
		return this.averageVotesText.replace(/\$\{num_of_votes\}/, numOfVotes).replace(/\$\{text_rating\}/, textRating);
	},
	
	/**
	 * @constant
	 * @return {string} Send to friend text for the widget: emailText
	 * @memberOf HD.community.Blog
	 */
	getEmailText : function() {
		return this.emailText;
	},
	
	/**
	 * @constant
	 * @return {string} Main template for the widget
	 * @memberOf HD.community.Blog
	 */
	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.Blog.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.Blog.hooks.MEDIA_RATING_TEXT;
	},
	
	/** 
	 * Main template for the widget
	 * @memberOf HD.community.Blog
	 * @type jst_template
	 */	
	html :  '\
		<div class="${classes.ITEM} ${classes.BLOG}{if !blog.previous} ${classes.FIRST}{/if}{if !blog.next} ${classes.LAST}{/if} ${hooks.MEDIA_ITEM}">\
			<div class="${classes.TITLE} ${hooks.MEDIA_TITLE}">${blog.title|ellipse:config.titleLength || blog.title.length}</div>\
			{if config.embedBlogDetailNavigation}\
			<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>\
			{/if}\
			<div class="${classes.RATING}">\
				<div class="${ratingClasses.AVERAGE_RATING} ${hooks.MEDIA_RATING_AVG}">\
					<div class="${ratingClasses.CAPTION} ${hooks.MEDIA_CAPTION}"></div> \
					<div class="${ratingClasses.STAR_RATING} ${hooks.MEDIA_RATING_STAR}"></div>\
					(<div class="${ratingClasses.NUM_OF_VOTES} ${hooks.MEDIA_VOTES}"></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>\
						${templates.getAverageVotesText(\'<div class="\'+templates.getVotesText()+\'"></div>\',\'<div class="\'+templates.getRatingText()+\'"></div>\')}\
					</div>\
				</div>\
			</div>\
			<table class="${classes.WRAPPER}">\
				<tr>\
					<td>\
						<div class="${classes.DATE}">\
							<div class="${classes.LABEL}">${templates.getDateLabel()}</div>\
							<div class="${classes.VALUE}">${blog.uploadedDate|date}</div>\
						</div>\
					</td>\
					<td>\
					{if !blog.hiddenAuthor}\
						<div class="${classes.AUTHOR} ${hooks.MEDIA_AUTHOR}">\
						 	<div class="${classes.LABEL}">${templates.getAuthorLabel()}</div>\
						 	<div class="${classes.VALUE}">${blog.author}</div>\
						 </div>\
					{else}\
						<div/>\
					{/if}\
					</td>\
				</tr>\
			</table>\
			<div class="${classes.CATEGORIES}">\
			{if blog.category}\
				<div class="${classes.LABEL}">${templates.getCategoryLabel()}</div>\
				<div class="${classes.VALUE}"><a class="${classes.CATEGORY} ${hooks.MEDIA_CATEGORY}" href="javascript:void(0)">${blog.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 blog.tags}{if tag_index > 0}${", "}{/if}<a class="${classes.TAG}{if _MODIFIERS.active(tag)} ${classes.ACTIVE}{/if} ${hooks.MEDIA_TAG}" href="javascript:void(0)">${tag}</a>{/for}\
				</div>\
			{/if}\
			</div>\
			<div class="${classes.THUMB} ${hooks.MEDIA_THUMB}"></div>\
			<div class="${classes.DESCRIPTION}">\
				<div class="${classes.FULL}">${blog.description}</div>\
				<div class="${classes.SHORT}">${shortDescription}</div>\
				{if hasMore}\
					<div class="${classes.MORE} ${hooks.MEDIA_MORE}">${templates.getMoreText()}</div> | \
				{/if}\
				<div class="hdCommentsButton ${hooks.MEDIA_COMMENTS_BTN}">\
					${templates.getCommentsText(blog.numberOfComments)}\
				</div>\
			</div>\
			{if config.embedShare}\
				${shareWidget|html}\
			{/if}\
			{if config.embedSendFriend}\
				${sendFriendWidget|html}\
			{/if}\
		</div>'
};

(function() {
	
	/**
	 * The collection of hooks
	 */
	HD.community.Blog.hooks = HD.clone(HD.community.Media.hooks);
})();

HD.community.Blog.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, model) {
		var blog = this.data;
		if(blog == null) {
			return "";
		}
		
		// Load templates from the dynamic config.
		this.loadTemplates(HD.community.Blog.templates, HD.community.Blog.hooks, { config: config, templates: 'blogTemplates', hooks: 'blogHooks'});
		
		var activeTags = model.filters && model.filters.tags ? model.filters.tags.slice(0) : [];
		var description = blog.description;
		var hasMore = false;
		
		// Generate short description.
		if(HD.util.Common.hasValue(description)) {
			// strip HTML tags from description to get the exact character count
			var strippedDescription = HD.util.Common.stripHtmlTags(description);
			// if stripped description is longer that preview length
			if(strippedDescription.length > config.previewLength) {
				// replace characters being preview length with '...' while preserving word boundaries
				description = HD.util.Common.ellipseText(description, config.previewLength, true);
				// display 'More' button
				hasMore = true;
			} else { // if description is short enough
				// still remove all the html tags to hide images in preview description
				description = HD.util.Common.stripHtmlTags(description, true);
			}
		}
		
		// 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(), {
			blog             : blog,
			config           : config,
			shortDescription : description,
			hasMore          : hasMore,
			shareWidget      : this.shareWidget || null,
			sendFriendWidget : this.sendFriendWidget || null,
			hasTags          : blog.tags && blog.tags.length > 0,
			ratingClasses    : HD.util.StarRating.CSS_CLASSES,
			_MODIFIERS       : {
				// Determine if a tag is active (user selected a tag as a search filter).
				active       : function(tag) {
					var active = false;
					for (var j = activeTags.length - 1; j >= 0; j--) {
						if (activeTags[j] == tag) {
							active = true;
							activeTags.splice(j,1);
							break;
						}
					}
					return active;
				},
				html         : function(widget) { return widget.getHtml(blog); }
			}
		});
	},
	
	/**
	 * Removes tooltip
	 */
	destroy : function() {
		if (this.tooltip) {
			this.tooltip.destroy();
			delete this.tooltip;
		}
	},
	
	/**
	 * Sets event listener for the widget.
	 * @param {HTMLElement} blogEl
	 *                 		Container for the blog display
	 * @param {object} 		widget
	 * 						Widget object calling the blog
	 */
    setListener : function(blogEl, widget) {
    	var classes = HD.CSS_CLASSES;
    	var ratingClasses = HD.util.StarRating.CSS_CLASSES;
    	var blog = this.data;
		if(blog == null) {
			return "";
		}

    	var cb = this;
    	var blogCb = blog;
    	var config = widget.config;
    	
    	var expandItemCallback = function() {
    		widget.notifyObservers.call(widget, "itemSelected", blogCb);
    		widget.model.setActiveItem.call(widget.model, blogCb);
    	};
    	
    	// Set click events
    	if(widget.config.type == 'hd_gallery_widget') {
    		var titleEl = widget.config.showMatrix ? blogEl : HD.getByClass(this.config.hooks.MEDIA_TITLE, '*', blogEl)[0];
    		if(titleEl){
    			titleEl.onclick = expandItemCallback;
    		}
    	}
    	
		var commentsEl = HD.getByClass(this.config.hooks.MEDIA_COMMENTS_BTN, '*', blogEl)[0];
		if (commentsEl){
			commentsEl.onclick = expandItemCallback;
		}
    	
    	var moreEls = HD.getByClass(this.config.hooks.MEDIA_MORE, '*', blogEl);
    	if(moreEls.length > 0) {
	    	moreEls[0].onclick = expandItemCallback;
    	}
    	
    	var thumbEl = HD.getByClass(this.config.hooks.MEDIA_THUMB, '*', blogEl)[0];
    	var imageEl = blog.description.match(/\<img.+?\>/);
    	
    	if(thumbEl && blog.url.indexOf("videos")> 0 || blog.url.indexOf("VIDEO")> 0) {
    		var player = new HD.util.Player({
    			parent : thumbEl,
				width: config.playerWidth || 400,
				height: config.playerHeight || 300,
				parentWidget : this,
				templates : config.playerTemplates || {},
				hooks     : config.playerHooks || {}
    		});
    		
    		player.view.render({
    			videoUrl : blog.url,
				thumbUrl : blog.largeThumbUrl || blog.thumbUrl,
				media : blog
    		});

			window.playerTest = player;
    	} else if(thumbEl && imageEl && imageEl[0]) {
			var src = imageEl[0].match(/src=["'](.+?)["']/);
			if (src && src[1]) {
	    	    var newImageEl = new Image();
	    	    newImageEl.src = src[1];
				thumbEl.appendChild(newImageEl);
			}
    	}

		// Attach category clicked events
		if (!!blog.category) {
			var catEl = HD.getByClass(this.config.hooks.MEDIA_CATEGORY, '*', blogEl);
			if (catEl[0]) {
				catEl[0].onclick = function() {
					widget.model.setCategories([blog.category]);
				};
			}
		}

		// Attach tag clicked events
		if (blog.tags && blog.tags.length > 0) {
			var tagEls = HD.getByClass(this.config.hooks.MEDIA_TAG, '*', blogEl);
			for (var i = 0, len = tagEls.length; i < len; i++) {
				(function() {
					var tag = blog.tags[i];
					tagEls[i].onclick = function() {
						widget.model.setTags([tag]);
					};
				})();
			}
		}
    	
    	/////////// RATING ////////////////
    	var myRatingEl = HD.getByClass(this.config.hooks.MEDIA_RATING_MY, '*', blogEl)[0] || null;
    	var avgRatingEl = HD.getByClass(this.config.hooks.MEDIA_RATING_AVG, '*', blogEl)[0] || null;
    	var ratingObserver = {
    		update : function(eventName, eventData) {
    			widget.model.rateMedia.call(widget.model, blogCb.mediaId, null, eventData);
    		}
    	};
		
		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;
			
			if (starRatingEl) {
				starRatingEl.onclick = expandItemCallback;
			}
			var staticRating = new HD.util.StarRating({
				// elements to render data in
				captionParent : captionEl,
				textRatingParent : textRatingEl,
				starRatingParent : starRatingEl,
				numOfVotesParent : numOfVotesEl,
		
				// data values
				numOfVotes : blog.numberOfVotes,
				averageRating : blog.rating,
	    		isStatic : true,
	    		itemId : blog.mediaId,
   		
	    		// 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 : blog.numberOfVotes,
				averageRating : blog.rating,
	    		isStatic : false,
	    		itemId : blog.mediaId,
   		
	    		// 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 == blogCb.mediaId) {
						blogCb.numberOfVotes = eventData.numberOfVotes;
						blogCb.rating = eventData.rating;
						
						cb.updateRatingWidgets.call(cb, eventData);
					}
				}
			}
		});
		
		var model = widget.model;
		
		var previousEl = HD.getByClass(this.config.hooks.MEDIA_PREVIOUS, '*', blogEl)[0];
		var nextEl = HD.getByClass(this.config.hooks.MEDIA_NEXT, '*', blogEl)[0];
		if(previousEl){
			if(model.hasPreviousItem()) {
				previousEl.onclick = function() {
					widget.view.notifyObservers.call(widget.view, "itemChange_Start", blog);
					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", blog);
					model.getNextItem.call(model);
				};
			} else {
				HD.addClass(nextEl, classes.HIDDEN);
			}
		}
		
		var authorEls = HD.getByClass(this.config.hooks.MEDIA_AUTHOR, '*', blogEl)
		if(authorEls.length > 0) {
			var authorEl = authorEls[0];
			
			authorEl.onclick = function() {
				widget.notifyObservers.call(widget, "authorSelected", blogCb);
				widget.model.getMemberProfile.call(widget.model, blogCb.authorId);
			};
		}
		
		// Update share/send friend widgets.
		if (widget.config.embedShare && this.shareWidget) {
			this.shareWidget.config.parent = blogEl;
			this.shareWidget.setListeners(blog);
		}
		if (widget.config.embedSendFriend && this.sendFriendWidget) {
			this.sendFriendWidget.config.parent = blogEl;
			this.sendFriendWidget.setListeners(blog);
		}
		
    }
};

HD.extend(HD.community.Blog, [HD.community.Media]);


HD.register('hd_blog', 'HD.community.Blog', {version: "1.0", build: "1"});
