/**
 * @class HD.CommentsWidget
 * @description The purpose of CommentsWidget is to provide a mechanism for users to read
 * 				and submit comments for media
 * 				Registered as hd_comments_widget.
 * @constructor
 * @extends HD.Widget
 * @see HD.CommentsWidget.hooks
 * @see HD.CommentsWidget.templates
 * @property {object} 	config
 *                    	The configuration for the widget.
 * @property {object} 	[config.hooks=HD.CommentsWidget.hooks]
 *                 		Customized subset of hooks (merged with the defaults).
 * @property {boolean} 	config.requiresLogin
 *                    	Whether a user must be logged in to submit a comment
 *                    	Default is false.
 * @property {boolean} 	submitAbove 
 * 						Show submission form above comments
 * 						Default is false
 * @property {boolean} 	submitBelow 
 * 						Show submission form below comments
 * 						Default is false
 * @property {boolean} 	confirmation 
 * 						Whether to show confirmation on comment submission
 * 						Default is false
 * @property {object} 	[config.templates=HD.TagCloudWidget.templates]
 *                 		Customized subset of templates (merged with the defaults).			         
 */
HD.CommentsWidget = function(config) {
    this.config = config || {};
	this.config.requiresLogin = this.config.requiresLogin || false;
	this.config.submitAbove = this.config.submitAbove || false;
	this.config.submitBelow = this.config.submitBelow || false;
	this.config.confirmation = this.config.confirmation || false;
    
	/** Observer collection */
    this.observers = [];
	this.loadTemplates(arguments.callee);
};

/**
 * The collection of default templates.
 * @fieldOf HD.CommentsWidget
 */
HD.CommentsWidget.templates = {
		
	/**
	 * Label for the widget
	 * @memberOf HD.CommentsWidget
	 */	
	titleLabel          : "Comments",
	
	/**
	 * Post comment label for the widget
	 * @memberOf HD.CommentsWidget
	 */	
	postCommentLabel    : "Post a Comment",
	
	/**
	 * Comment field label for the widget
	 * @memberOf HD.CommentsWidget
	 */	
	commentFieldLabel   : "Comment:",
	
	/**
	 * Submit comment label for the widget
	 * @memberOf HD.CommentsWidget
	 */	
	submitLabel         : "Submit",
	
	/**
	 * Loading text for the widget
	 * @memberOf HD.CommentsWidget
	 */	
	loadingText         : "Loading comments...",
	
	/**
	 * No comments text for the widget
	 * @memberOf HD.CommentsWidget
	 */	
	noCommentsText      : "This item has no comments, be the first to leave your mark.",
	
	/**
	 * Confirmation label for the widget
	 * @memberOf HD.CommentsWidget
	 */	
	confirmationLabel   : "Thank You",
	
	/**
	 * Confirmation text for the widget
	 * @memberOf HD.CommentsWidget
	 */	
	confirmationValue   : "Thank you for your submission. After a quick review, your content will be posted to the website within one or two business days. Content deemed to be off topic, offensive or promoting dangerous riding cannot be posted.",
	
	/**
	 *Submit another comment text for the widget
	 * @memberOf HD.CommentsWidget
	 */	
	submitAnotherText   : "Post another comment",
	
	/**
	 * Conditions short text for the widget
	 * @memberOf HD.CommentsWidget
	 */	
	termsConditionsShortPreText    : "By submitting my comment I agree to the following",
	
	/**
	 * Terms and conditions button text for the widget
	 * @memberOf HD.CommentsWidget
	 */	
	termsConditionsShortHandleText : "Terms and Conditions.",
	
	/**
	 * TBD
	 * @memberOf HD.CommentsWidget
	 */	
	termsConditionsShortPostText   : "",
	
	/**
	 * Terms and conditions text for the widget
	 * @memberOf HD.CommentsWidget
	 */	
	termsConditionsText : "By submitting this content, I consent that all videos, photographs, my name, my story and any other reproductions of my information and likeness (the &ldquo;Materials&rdquo;) may be used by Harley-Davidson, Its affiliates (collectively referred to as &ldquo;Harley-Davidson&rdquo;) and/or others with its consent, for the purpose of illustration, advertising, promotions, duplication or publication or for any other purpose in any manner and in any media without further consideration. I represent and warrant that I am the owner of the Materials and have the rights to dispose of my ownership rights as I see fit. I hereby assign to Harley-Davidson all rights, title and interest in the Material and any other tangible medium of expression of my image and information including all copyrights therein that I provide to Harley-Davidson.",
	
	/**
	 * @constant
	 * @return {string} Label for the widget: titleLabel
	 * @memberOf HD.CommentsWidget
	 */
	getTitleLabel : function(){
		return this.titleLabel;
	},
	
	/**
	 * @constant
	 * @return {string} Post comment label for the widget: postCommentLabel
	 * @memberOf HD.CommentsWidget
	 */
	getPostCommentLabel : function(){
		return this.postCommentLabel;
	},
	
	/**
	 * @constant
	 * @return {string} Comment field label for the widget: commentFieldLabel
	 * @memberOf HD.CommentsWidget
	 */
	getCommentFieldLabel : function(){
		return this.commentFieldLabel;
	},
	
	/**
	 * @constant
	 * @return {string} Submit button label for the widget: submitLabel
	 * @memberOf HD.CommentsWidget
	 */
	getSubmitLabel : function(){
		return this.submitLabel;
	},
	
	/**
	 * @constant
	 * @return {string} Loading comments text for the widget: loadingText
	 * @memberOf HD.CommentsWidget
	 */
	getLoadingText : function(){
		return this.loadingText;
	},
	
	/**
	 * @constant
	 * @return {string} No comments text for the widget: noCommentsText
	 * @memberOf HD.CommentsWidget
	 */
	getNoCommentsText : function(){
		return this.noCommentsText;
	},
	
	/**
	 * @constant
	 * @return {string} Confirmation label for the widget: confirmationLabel
	 * @memberOf HD.CommentsWidget
	 */
	getConfirmationLabel : function() {
		return this.confirmationLabel;
	},
	
	/**
	 * @constant
	 * @return {string} Confirmation text for the widget: confirmationValue
	 * @memberOf HD.CommentsWidget
	 */
	getConfirmationValue : function() {
		return this.confirmationValue;
	},
	
	/**
	 * @constant
	 * @return {string} Submit another comment text for the widget: submitAnotherText
	 * @memberOf HD.CommentsWidget
	 */
	getSubmitAnotherText : function() {
		return this.submitAnotherText;
	},
	
	/**
	 * @constant
	 * @return {string} Short terms and conditions text for the widget: termsConditionsShortPreText
	 * @memberOf HD.CommentsWidget
	 */
	getTermsConditionsShortPreText : function() {
		return this.termsConditionsShortPreText;
	},
	
	/**
	 * @constant
	 * @return {string} Terms and conditions button text for the widget: termsConditionsShortHandleText
	 * @memberOf HD.CommentsWidget
	 */
	getTermsConditionsShortHandleText : function() {
		return this.termsConditionsShortHandleText;
	},
	
	/**
	 * @constant
	 * @return {string} TBD: termsConditionsShortPostText
	 * @memberOf HD.CommentsWidget
	 */
	getTermsConditionsShortPostText : function() {
		return this.termsConditionsShortPostText;
	},
	
	/**
	 * @constant
	 * @return {string} Terms and conditions text for the widget: termsConditionsText
	 * @memberOf HD.CommentsWidget
	 */
	getTermsConditionsText : function() {
		return this.termsConditionsText;
	},
	
	/**
	 * @constant
	 * @return {string} Error template for the widget
	 * @memberOf HD.CommentsWidget
	 */
	getErrorsHtml : function() {
		return this.errorsHtml;
	},
	
	/**
	 * @constant
	 * @return {string} Main template for the widget
	 * @memberOf HD.CommentsWidget
	 */
	getHtml : function() {
		return this.html;
	},
	
	/** 
	 * Error template for the widget
	 * @memberOf HD.CommentsWidget
	 * @type jst_template
	 */	
	errorsHtml : '\
		{if errors}\
			{for error in errors}\
				<div class="${classes.ERROR}">${error.errorMessage}</div>\
			{/for}\
		{/if}',
	
	/** 
	 * Main template for the widget
	 * @memberOf HD.CommentsWidget
	 * @type jst_template
	 */			
	html :  '\
		{if comments}\
			{macro commentsForm()}\
				<li><form class="${hooks.FORM}">\
					<div class="${classes.TITLE}">${templates.getPostCommentLabel()}</div>\
					<div class="${classes.WRAPPER} ${hooks.ERROR}"></div>\
					<div class="${classes.LABEL}">${templates.getCommentFieldLabel()}</div>\
					<textarea cols="30" rows="5" class="${classes.VALUE} ${hooks.TEXTAREA}"></textarea><br/>\
					<div class="${classes.AGREEMENT}">\
						<div class="${classes.LABEL} ${hooks.LEGAL_SM}">\
							${templates.getTermsConditionsShortPreText()} <span class="${classes.HANDLE} ${classes.CONTROL}  ${hooks.TERMS_BUTTON}">${templates.getTermsConditionsShortHandleText()}</span> ${templates.getTermsConditionsShortPostText()}\
						</div>\
						<div class="${classes.VALUE} ${classes.HIDDEN} ${hooks.LEGAL_FULL}">\
							<div style="margin-top:10px;">${templates.getTermsConditionsText()}</div>\
						</div>\
					</div>\
					<input type="Submit" value="${templates.getSubmitLabel()}"/>\
				</form></li>\
				<li class="${classes.HIDDEN}">\
					<div class="${classes.CONFIRMATION} ${hooks.CONFIRMATION}">\
						<div class="${classes.LABEL}">${templates.getConfirmationLabel()}</div>\
						<div class="${classes.VALUE}">${templates.getConfirmationValue()}</div>\
						<div class="hdSubmitComment hdSubmitAnotherComment ${hooks.SUBMIT_ANOTHER_COMMENT}">${templates.getSubmitAnotherText()}</div>\
					</div>\
				</li>\
			{/macro}\
			<div class="${classes.COMMENTS} ${classes.WIDGET}">\
				<ul>\
				{if config.submitAbove}\
					${commentsForm()}\
				{/if}\
				{if comments.length > 0}\
					<li class="${classes.TITLE}">${templates.getTitleLabel()}</li>\
					{for comment in comments}\
						<li class="${classes.COMMENT}">\
							<div>\
								<span class="${classes.DATE}">${comment.createdDate|date}</span> \
								<span class="${classes.AUTHOR}">${comment.submittedBy}</span>\
							</div>\
							<div class="${classes.VALUE}">${comment.text}</div>\
						</li>\
					{/for}\
				{else}\
					<li class="${classes.EMPTY}">${templates.getNoCommentsText()}</li>\
				{/if}\
				</ul>\
			</div>\
			{if config.submitBelow}\
				${commentsForm()}\
			{/if}\
		{else}\
			${templates.getLoadingText()}\
		{/if}'
};

(function() {
	var classes = HD.CSS_CLASSES;
	
	/**
	 * The collection of hooks
	 */
	HD.CommentsWidget.hooks = {
		
		/**
		 * Standalone: (1)<br />
		 * Use: Submit comment form<br />
		 * Type: Form<br />
		 * @memberOf HD.CommentsWidget
		 */
		FORM : classes.COMMENTS + '-form',
		
		/**
		 * Dependencies: 1: FORM <br/>
		 * Use: Comment field<br />
		 * Type: Textarea
		 * @memberOf HD.CommentsWidget
		 */
		TEXTAREA : classes.COMMENTS + '-textarea',
		
		
		/**
		 * Standalone: (1)<br />
		 * Use: Short legal description container<br />
		 * @memberOf HD.CommentsWidget
		 */
		LEGAL_SM : classes.COMMENTS + '-legal-sm',
		
		/**
		 * Standalone: (1)<br />
		 * Use: Full legal description container<br />
		 * @memberOf HD.CommentsWidget
		 */
		LEGAL_FULL : classes.COMMENTS + '-legal-full',
		
		/**
		 * Standalone: (1)<br />
		 * Use: Shows/Hides the legal description<br />
		 * @memberOf HD.CommentsWidget
		 */
		TERMS_BUTTON : classes.COMMENTS + '-terms-btn',
		
		/**
		 * Dependencies: 1: FORM <br/>
		 * Use: Refreshes the submission form after successful submission<br />
		 * @memberOf HD.CommentsWidget
		 */
		SUBMIT_ANOTHER_COMMENT : classes.COMMENTS + '-submit-comment',
		
		/**
		* Dependencies: 1: FORM <br/>
		 * Use: Loader on comment submission<br />
		 * @memberOf HD.CommentsWidget
		 */
		COMMENT_SUBMITTED : classes.COMMENTS + '-' + classes.LOADING,
		
		/**
		 * Dependencies: 1: FORM <br/>
		 * Use: Error container<br />
		 * @memberOf HD.CommentsWidget
		 */
		ERROR : classes.COMMENTS + '-error',
		
		/**
		 * Dependencies: 1: FORM <br/>
		 * Use: Confirmation container<br />
		 * @memberOf HD.CommentsWidget
		 */
		CONFIRMATION : classes.COMMENTS + '-confirmation'

		
	};
})();

HD.CommentsWidget.prototype = {
    
	/**
	 * Sets event listeners for the widget.
	 * @param {object} [data]
	 *                 Event data from the render phase
	 */
    setListeners : function(data) {
    	if(data == null) {
    		return;
    	}
    	
    	var classes = HD.CSS_CLASSES;
    	var parentEl = this.getParent();
    	
    	// Get the submission elements
    	var formEl = HD.getByClass(this.config.hooks.FORM, '*', parentEl)[0];
    	var commentEl = HD.getByClass(this.config.hooks.TEXTAREA, '*', parentEl)[0];
    	
    	// Initialize the form and set submit event
    	if(formEl && commentEl) {
    		HD.removeClass(formEl, classes.ERROR);
	    	var modelCb = this.model;
    		var mediaCb = data;
			var cb = this;

    		formEl.onsubmit = function() {
    			// Get the submission
    			var filteredCommentValue = HD.util.Common.stripHtmlTags(commentEl.value);
				var submitComment = function() {
	    			modelCb.submitComment.call(modelCb, mediaCb.mediaId, mediaCb.contentType, filteredCommentValue);
				};
				// Force a login check if required.
				if (cb.config.requiresLogin) {					
					login.model.isUserLoggedIn(function(userResponse) {
						if(userResponse.loggedInLevel > 1) {
							submitComment();
						} else {
							var observer = {
								update : function(eventName, eventData) {
									if (eventName == "logged_In") {
										submitComment();
										login.model.removeObserver(this);
										HD.util.Common.getObservable().removeObserver(this);
									} else if (eventName == "overlayClose_Click") {
										login.model.removeObserver(this);
										HD.util.Common.getObservable().removeObserver(this);
									}
								}
							};
					
							HD.util.Common.getObservable().addObserver(observer);
							login.model.addObserver(observer);
					
							if(userResponse.loggedInLevel > 0){
								login.view.promptCreateScreenName();
							}else{
								login.view.promptAuthentication();
							}
						}
					});
				}
				// Otherwise submit the comment like normal.
				else {
					submitComment();
				}
    			return false;
    		};
    		
    		// Toggle the terms and conditions
    		var partialLegalEl = HD.getByClass(this.config.hooks.LEGAL_SM, '*', parentEl)[0];
    		var fullLegalEl = HD.getByClass(this.config.hooks.LEGAL_FULL, '*', parentEl)[0];
    		
    		var legalTriggerEl = HD.getByClass(this.config.hooks.TERMS_BUTTON, '*', parentEl)[0];
    		
    		if(legalTriggerEl && fullLegalEl){
	    		legalTriggerEl.onclick = function() {
	    			if(HD.hasClass(fullLegalEl, classes.HIDDEN)) {
	    				HD.removeClass(fullLegalEl, classes.HIDDEN)
	    			} else {
	    				HD.addClass(fullLegalEl, classes.HIDDEN)
	    			}
	    		};
    		}
    	}
    	
    	// Set the click even to submit another comment
    	var cb = this;
    	var confirmationEl = HD.getByClass(this.config.hooks.SUBMIT_ANOTHER_COMMENT, '*', parentEl)[0];
    	if(confirmationEl != null) {
	    	confirmationEl.onclick = function() {
	    		cb.hideConfirmation.call(cb);
	    	};
    	}
    	
    	//var authorEls = HD.getByClass(classes.AUTHOR, "span", parentEl);
		//var comments = data.comments;
		//for(var i = 0, len = authorEls.length; i < len; i++) {
		//	this.setAuthorListener(authorEls[i], comments[i]);
		//}
    },
    
    /**
	 * Sets author listeners for the widget to show profile.
	 * @param {HTMLElement} element
	 *                 		Element to be clicked
	 * @param {string}		authorId
	 * 						Author ID of the profile to be shown
	 */
    setAuthorListener : function(element, authorId) {
    	if(element == null || authorId == null) {
    		return;
    	}
    	
    	var cb = this;
    	element.onclick = function() {
    		cb.notifyObservers.call(cb, "authorSelected", authorId);
    		cb.model.getMemberProfile.call(cb.model, authorId);
    	};
    },
    
    /**
	 * Monitors events by HD.CommentsWidget.
	 * @param {string} eventName
	 *                 The name of the event
	 * @param {object} [eventData]
	 *                 Data for the event
	 */
    update : function(eventName, eventData) {
    	
    	var classes = HD.CSS_CLASSES;
    	var parentEl = this.getParent();
		var inputEl = HD.getByClass(this.config.hooks.TEXTAREA, '*', parentEl)[0];
    	
    	if(eventName == "getComments_Start") {
    		this.loading(true);
    		this.render(eventData);
    	} else if(eventName == "getComments_Finish") {
    		this.loading(false);
    		this.render(eventData);
    	} 
    	else if(eventName == "submitComment_Start") {
    		
    		if(inputEl){
        		HD.addClass(inputEl, this.config.hooks.COMMENT_SUBMITTED);
        	}
    	}
    	else if(eventName == "submitComment_Finish") {
    		this.loading(false);
    		if(inputEl){
        		HD.removeClass(inputEl, this.config.hooks.COMMENT_SUBMITTED);
        	} 
    		if(this.config.confirmation) { 
    			this.showConfirmation(eventData);
    		} else {
    			this.render(eventData);
    		}
    	} else if(eventName == "submitComment_Error") {
    		this.loading(false);
    		if(inputEl){
        		HD.removeClass(inputEl, this.config.hooks.COMMENT_SUBMITTED);
        	}    		
    		this.renderError(eventData);
    	}
    },
    
    /**
	 * Shows the confirmation after successful submission
	 */
    showConfirmation : function() {
    	var classes = HD.CSS_CLASSES;
    	var parentEl = this.getParent();
    	
    	var formEl = HD.getByClass(this.config.hooks.FORM, '*', parentEl)[0];
    	var textareaEl = HD.getByClass(this.config.hooks.TEXTAREA, '*', parentEl)[0];
    	var errorWrapperEl = HD.getByClass(this.config.hooks.ERROR, '*', parentEl)[0];
    	var confirmationEl = HD.getByClass(this.config.hooks.CONFIRMATION, '*', parentEl)[0];
    	
    	if(textareaEl){
    		textareaEl.value = "";
    	}
    	
    	if(formEl){
    		HD.addClass(formEl.parentNode, classes.HIDDEN);
    		HD.removeClass(formEl, classes.ERROR);
    	}
   		
    	if (errorWrapperEl){
    		errorWrapperEl.innerHTML = '';
    	}
    	
    	if (confirmationEl){
    		HD.removeClass(confirmationEl.parentNode, classes.HIDDEN);
    	}
    },
    
    /**
	 * Hides the confirmation
	 */
    hideConfirmation : function() {
    	var classes = HD.CSS_CLASSES;
    	var parentEl = this.getParent();
    	var formEl = HD.getByClass(this.config.hooks.FORM, '*', parentEl)[0];
    	var confirmationEl = HD.getByClass(this.config.hooks.CONFIRMATION, '*', parentEl)[0];
    	
    	if (confirmationEl){
    		HD.addClass(confirmationEl.parentNode, classes.HIDDEN);
    	}
    	
    	if(formEl){  	
    		HD.removeClass(formEl.parentNode, classes.HIDDEN);
    	}
    },
    
    /**
	 * Shows errors upon comment submission
	 * @param {object} errors
	 *                 The errors returned
	 */
    renderError : function(errors) {

    	var classes = HD.CSS_CLASSES;
    	var parentEl = this.getParent();
    	
    	var formEl = HD.getByClass(this.config.hooks.FORM, '*', parentEl)[0];
    	var errorWrapperEl = HD.getByClass(this.config.hooks.ERROR, '*', parentEl)[0];
    	
    	if (formEl){
    		HD.addClass(formEl, classes.ERROR);
    	}
   		
    	if (errorWrapperEl){
    		errorWrapperEl.innerHTML = this.getErrorsHtml(errors);
    	}
    },
    
    /**
	 * Renders the Error HTML for the widget based on dynamic data.
	 * @param {object} [errors]
	 *                 Event data from the render phase
	 * @returns {string} Error HTML for the widget
	 */
    getErrorsHtml : function(errors) {
		return this.processTemplate(this.config.templates.getErrorsHtml(), {
			errors : errors
		});
    },
    
    /**
	 * 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(data) {
		var self = this;
		return this.processTemplate(this.config.templates.getHtml(), {
			comments : (data && data.comments) || null
		});
    }
};

HD.extend(HD.CommentsWidget, [HD.Widget]);

HD.register('hd_comments_widget', 'HD.CommentsWidget', {version: "1.0", build: "1"});