////
// Plugin - commentForm
//
(function(){
	// Constructor
	(CommentForm = function(element, options) {

		this.form = jQuery(element);
		// Merge options with default values
		this.settings = jQuery.extend({}, this.defaultValues, options || {});
		this.init();
	}).prototype = {
		form : null,
		content : null,
		submitter : null,
		errorDialogHandler: null,
		commentedEntityUUID : null,

		defaultValues : {
			'contentInitialTxt' : '',
			'contentDefaultTxt' : '',
			'removeCommentTxt' : '',
			'deleteCommentConfirmationTitleTxt' : '',
			'deleteCommentConfirmationQuestionTxt' : '',
			'deleteCommentErrorTxt' : '',
			'deleteButtonTxt' : '',
			'cancelButtonTxt' : '',
			'textAreaSelector' : 'textarea.CommentTextbox',

			'contentClass' : '',
			'contentClassInitial' : '',
			'commentListClassSelector' : '.CommentList',
			'commentDeleteButtonClass': 'CommentRemoveButton',
			'submitClass' : '',
			'context' : '',
			'noAutosizeClass' : '',
			'isModerator' : false,
			/**Callback parameter: jqXHR, textStatus, errorThrown*/
			'failedCreatedCommentCallback': function(){},
			/**Callback parameter: data*/
			'successfulCreatedCommentCallback': function(){}
		},
		REQUESTS_IN_PROGRESS : 0,
		blurTimer : null,
		commentRemoveButtonHTML : null,

		init : function() {
			this.initEnvironmentVariables();
			this.initSubmitHandling();
			this.initTailHandling();
			this.initFocusLostHandling();
			this.initDeleteHandling();
		},


		/* ****************************************************************
		 * 						initialization
		 * ***************************************************************/

		initEnvironmentVariables : function () {
			var settings = this.settings;

			this.findUUID();
			
			this.errorDialogHandler = this.settings['errorDialogHandler'];

			// Get textarea of new comment
			this.content = jQuery('.' + settings['contentClassInitial'], this.form);

			// Set default value in "Description" field
			this.content.assistantInput({
				'initialText' : settings['contentInitialTxt'],
				'defaultText' : settings['contentDefaultTxt'],
				'classNameInitial' : settings['contentClassInitial'],
				'className' : settings['contentClass'],
				'validationFunction' : jQuery.proxy(this.validateInput, this)
			});

			// Assign both elements in a feed
			this.form.assistantFeed({
				'title' : null,
				'content' : this.content,
				'comingUpFunction' : null/*jQuery.proxy(this.showContentTextareaAnimated, this)*/,
				'resetFunction' : jQuery.proxy(this.reset, this),
				'noAutosizeClass' : settings["noAutosizeClass"]
			});
			
			// Get submit button
			if(jQuery('.' + settings['submitClass']).length>0){
				this.submitter = jQuery(jQuery('.' + settings['submitClass']).get(0));
			}
			else{
				this.submitter=null;
			}
			this.tailSubmitter = jQuery('.' + 'commentTailLoader', this.form);

			this.textArea = this.form.find(this.settings['textAreaSelector']);

		},


		initSubmitHandling : function () {
			if(this.submitter){
				this.submitter.on('click', jQuery.proxy(this.sendCreateComment, this));
			}else{
				this.textArea.on('keydown', jQuery.proxy(this.keyPressed, this));
			}
			this.validateInput();
		},
		
		findUUID : function(){
			
			var uuidContainerCandidates = ['commentListClassSelector','textAreaSelector'];
			
			for(var i=0;i<uuidContainerCandidates.length;i++){
				var candidate = this.form.find(this.settings[uuidContainerCandidates[i]]);
				
				if(candidate && candidate.length>0){
					var id = candidate.attr('id');
					this.commentedEntityUUID = id.split("_")[1];
					break;
				}
			}
		},

		keyPressed : function (event){
			if (event.shiftKey && event.key === 'Enter') {
				return;
			}else if( event.key === 'Enter') {
				 event.preventDefault();
				 event.stopPropagation();
				 event.stopImmediatePropagation();
				 this.sendCreateComment(event);
				 return;
			  }
		},

		initTailHandling : function () {
			this.tailSubmitter.on('click', jQuery.proxy(this.sendTail, this));
		},

		initFocusLostHandling : function() {
			var funcGain = jQuery.proxy(this.focusGained, this );
			this.getAllFormElements().on('focus', funcGain);

			var funcLost = jQuery.proxy(this.focusLost, this );
			this.getAllFormElements().on('blur', funcLost);
		},

		initDeleteHandling : function() {
			jQuery(this.form).find('.'+this.settings['commentDeleteButtonClass']).on('click', jQuery.proxy( function(event) {
					this.deleteComment( jQuery(event.currentTarget).closest('.CommentEntry') );
				}, this)
			);
		},


		/* ****************************************************************
		 * 						input validation
		 * ***************************************************************/

		validateInput : function () {
			var isInvalid = (!this.isInputValid() || this.isRequestInProgress());
			if(this.submitter){
				this.setDisabled(isInvalid);
			}
		},

		isInputValid : function () {
			var isValidFeed = this.form.af_isValid();
			return isValidFeed;
		},

		isRequestInProgress : function () {
			return this.REQUESTS_IN_PROGRESS > 0;
		},

		setDisabled : function (disable){
			if(disable){
				if(this.submitter){
			//		this.submitter.prop('disabled','disabled');
				}else{
					this.textArea.prop('readonly', 'readonly');
				}
			}else{
				if(this.submitter){
					this.submitter.removeProp('disabled');
				}else{
					this.textArea.removeProp('readonly');
				}
			}
		},

		/* ****************************************************************
		 * 					Delete Comment
		 * ***************************************************************/


		deleteComment : function(commentElem) {
			var me = this;
			var dialogDiv = jQuery('div#dialog-confirm');
			dialogDiv.html('<p>'+this.settings['deleteCommentConfirmationQuestionTxt']+'</p>');

			var titleTxt = this.umescapeHtmlText(this.settings['deleteCommentConfirmationTitleTxt']);
			var okTxt = this.umescapeHtmlText(this.settings['deleteButtonTxt']);
			var cancelTxt = this.umescapeHtmlText(this.settings['cancelButtonTxt']);

			dialogDiv.dialog({
	            resizable: false,
	            height:160,
	            width:340,
	            modal: true,
	            title : titleTxt,

	            buttons: [
	                       {
	                    	   text: okTxt,
	                    	   click: function() {
	                    		   jQuery( this ).dialog( "close" );
	                    		   me.sendDeleteComment(commentElem);
	                    	   }
	                       },
	                       {
	                    	   text: cancelTxt,
	                    	   click: function() {
	                    		   jQuery( this ).dialog( "close" );
	                    	   }
	                       }

	            ]
	        });
		},

		sendDeleteComment : function(commentElem) {
			var commentUUIDToDelete = commentElem.attr('id').split('_')[1];

			var deleteElement = commentElem;

			var parentToDeleteWithEntrySelector = this.settings['deleteWithParentSelector'];
			if(parentToDeleteWithEntrySelector){
				var parentElem = jQuery(commentElem).closest(parentToDeleteWithEntrySelector);
				if(parentElem && parentElem.length > 0){
					deleteElement = parentElem;
				}
			}

			var context = this.settings['context'];
			var path = context+"/comment/comments/" + commentUUIDToDelete + "/";

			jQuery.ajax({
	            type : 'DELETE',
				url : path,
				success :  jQuery.proxy(function() {
					if (deleteElement.parent().hasClass('InsertedComment')) {
						deleteElement = deleteElement.parent();
					}
					deleteElement.fadeOut(function() {
						var prev = jQuery(deleteElement).prev()[0];
						if (prev && prev.classList.contains('SubSectionSeparator')) {
							prev.remove();
						}
						$(deleteElement).remove();
					});
					this.updateCommentDeleteButtons();
					if(this.form.parent().hasClass('NewsfeedEntry')) {
						this.updateNewsfeedDeleteButton();
					}
				},this),
				error :  jQuery.proxy(function() {
					this.errorDialogHandler.showErrorMsg('Error', this.settings['deleteCommentErrorTxt']);
				},this)
			});
		},



		/* ****************************************************************
		 * 					Browser <-> Server - Communication
		 * ***************************************************************/

		sendCreateComment : function(event) {
			var canSubmit = (this.isInputValid() && !this.isRequestInProgress())

			if(!canSubmit){
				this.settings['successfulCreatedCommentCallback'](null);
				return;
			}
			//submit button
			var element = event.currentTarget;

			var formValues = this.form.af_getValueArray();
			var comment = formValues['content'];
			var context = this.settings['context'];

			var path = context + '/comment/entities/' + this.commentedEntityUUID + '/';

			var dataMap = {'comment' : comment};
			var postData = JSON.stringify(dataMap);

			var errorHandler = function(jqXHR, textStatus, errorThrown) {
				this.settings['failedCreatedCommentCallback'](jqXHR, textStatus, errorThrown);
				if(window.console){
					if(window.console.log){
						window.console.log(textStatus);
					}
				}
			};

			jQuery.ajax({
				url : path,
				success : jQuery.proxy(function(responseHTML) {
					this.putCommentsIntoView(responseHTML,"fadeIn","slow");
					this.settings['successfulCreatedCommentCallback'](responseHTML);
				}, this),
				error : jQuery.proxy(errorHandler,this),
				data : postData,
				dataType : "html",
				contentType : "application/json; charset=utf-8",
				type : "POST"
			});
		},

		putCommentsIntoView : function(responseHTML, transistionFunction, transistionFunctionData)	{
			
			var newItem = jQuery('<div class="InsertedComment">' + responseHTML + '</div>').hide();
			var parent;
			var tmp = jQuery('#commentsHead_' + this.commentedEntityUUID);
			if(tmp && tmp.length > 0){
				parent=tmp;
			}else{
				tmp = jQuery('#CommentList_' + this.commentedEntityUUID);
				if(tmp && tmp.length > 0){
					var newParent = jQuery('<div id="commentsHead_'+this.commentedEntityUUID+'" class="commentsHead"></div>');
					tmp.append(newParent);
					parent = newParent;
				}
			}

			if(parent && parent.length > 0){
				newItem.appendTo(parent)[transistionFunction](transistionFunctionData);
			}

			this.updateCommentDeleteButtons();

			if (!this.settings['isModerator']) {
				jQuery('#delete_newsfeed_' + this.commentedEntityUUID).remove();
			}

			this.reset();
		},

		removeAllVisibleComments : function()
		{
			jQuery('#commentsHead_' + this.commentedEntityUUID).empty();
		},

		sendTail : function(event) {

			var element = event.currentTarget;

			this.headSize = this.getAllVisibleComments().length;

			var path = this.settings['context'] + '/comment/entities/' + this.commentedEntityUUID + '/tail/';

			jQuery.ajax(path, {
				success : jQuery.proxy(function(responseHTML) {

					var newRoot = jQuery('<div class="commentTextArea">' + responseHTML + '</div>');
					newRoot.hide();
					newRoot.appendTo('#commentsTail_' + this.commentedEntityUUID).fadeIn('slow');

					this.addCommentDeleteButtonOnAllElements();
					this.bindDeleteListenerOnAllElements(newRoot);

					jQuery('#commentsTailLoader_' + this.commentedEntityUUID).remove();
				}, this),
				type : 'GET',
				beforeSend : jQuery.proxy(function(xhr) {
					xhr.setRequestHeader('X-COMMENT-HEAD-SIZE', this.headSize);
				}, this)
			});
		},

		/* ****************************************************************
		 * 					delete button updates
		 * ***************************************************************/

		bindDeleteListenerOnAllElements  : function(rootElement) {
			
			var me = this;
			rootElement.find('.'+this.settings['commentDeleteButtonClass']).each(function(index, elem){
				me.bindDeleteListener(elem);
			});
		},

		bindDeleteListener : function(elem) {

			jQuery(elem).on('click', jQuery.proxy( function(event) {
					this.deleteComment( jQuery(event.currentTarget).closest('.CommentEntry') );
				}, this)
			);
		},

		removeAllCommentDeleteButtons : function() {
			// save button before delete
			this.commentRemoveButtonHTML = new XMLSerializer().serializeToString(jQuery('div.CommentRemoveButton > svg').get(0));

			var visibleComments = this.getAllVisibleComments();
			for (var i=0; i < visibleComments.length; ++i){
				var comment = jQuery(visibleComments[i]);
				var uuid = comment.attr('id').split('_')[1];
				var commentText=this.form.find('#comment_'+uuid+' .CommentText');
				if(commentText && commentText.length > 0){
					var removeButton = jQuery(commentText).find('.'+this.settings['commentDeleteButtonClass']);
					if(removeButton && removeButton.length > 0){
						removeButton.off('click');
						removeButton.remove();
					}
				}
			}
		},

		addCommentDeleteButtons : function(uuidList) {

			for (var i=0; i < uuidList.length; ++i){
				var uuid = uuidList[i];
				var commentText=this.form.find('#comment_'+uuid+' .CommentText');
				this.addButtonToComment(commentText, this.settings);
			}
		},

		addCommentDeleteButtonOnAllElements : function() {
			var func = jQuery.proxy(this.addButtonToComment, this);
			var add = jQuery.proxy(
				function(index, element) {
					func(jQuery(element));
				}
			, this);
			jQuery('.WithRemoveButton').each(add);
		},
		
		addButtonToComment : function (commentText) {
			if(commentText) {
				var removeButton = jQuery(commentText).find('.'+this.settings['commentDeleteButtonClass']);
				if(!removeButton || removeButton.length==0){
					var titleTxt = this.settings['removeCommentTxt'];
					commentText = commentText.prepend('<div class="'+this.settings['commentDeleteButtonClass']+'" title="'+ titleTxt +'">'+ this.commentRemoveButtonHTML +'</div>');
					var deleteButton = jQuery(commentText).find('.'+this.settings['commentDeleteButtonClass']);
					this.bindDeleteListener(deleteButton);
				}
			}
		},

		
		updateCommentDeleteButtons : function() {

			var context = this.settings['context'];
			var path = context + '/comment/entities/'+ this.commentedEntityUUID +'/deleteables/';

			jQuery.ajax({
	            type : 'GET',
	            dataType: 'json',
				url : path,
				success :  jQuery.proxy(function(data) {

					this.removeAllCommentDeleteButtons();

					var list = data['compactUUIDList'];
					this.addCommentDeleteButtons(list);
				},this),
				error :  jQuery.proxy(function(xhr) {
					if(window.console){
						if(window.console.log){
							window.console.log("failed to update deletable comments after of commented entity " + this.commentedEntityUUID);
						}
					}
				},this)
			});
		},

		updateNewsfeedDeleteButton: function () {
			if (this.settings['isModerator']) {
				return;
			}
			var newsFeedEntry = jQuery('#newsfeed_' + this.commentedEntityUUID);
			if (newsFeedEntry.find('.CommentEntry').length > 1) {
				return;
			}
			jQuery.ajax({
				type: 'GET',
				dataType: 'html',
				url: this.settings['context'] + '/newsfeed/' + this.commentedEntityUUID + "/",
				success: function (data) {
					var removeButton = jQuery.parseHTML(data)[1].querySelector('.NewsfeedRemoveButton');
					if (removeButton) {
						newsFeedEntry.find('.NewsfeedTitle').prepend(removeButton);
						jQuery('.NewsfeedForm').trigger('addedDeleteButton');
					}
				},
				error: jQuery.proxy(function () {
					window.console && window.console.log
					&& window.console.log("failed to get delete status of news feed", this.commentedEntityUUID);
				}, this)
			});
		},

		/* ****************************************************************
		 * 					response handling / ui update
		 * ***************************************************************/

		reset : function() {
			this.REQUESTS_IN_PROGRESS = 0;

			this.clearFocusTimer();

			// Set default values in form elements, force resizing of textarea
			this.form.af_reset();

			this.validateInput();
		},


		/* ****************************************************************
		 * 						blur timer
		 * ***************************************************************/

		focusGained : function(){
			//console.log('focus gained');
			this.clearFocusTimer();
		},

		focusLost : function(){
			//console.log('focus lost');
			var me = this;
			this.blurTimer = setTimeout(function(){
				//console.log('timer hit');
				if(!me.isDirty()){
					me.blurTimer = null;
				}
    	  }, 500);
		},

		clearFocusTimer : function(){
			if(this.blurTimer){
				clearTimeout(this.blurTimer);
				this.blurTimer = null;
			}
		},

		/* ****************************************************************
		 * 						help functions
		 * ***************************************************************/

		getAllFormElements : function () {
			return jQuery(this.settings['allFormElementsSelector']);
		},

		getAllVisibleComments : function () {
			return jQuery(".CommentEntry",this.form);
		},


		isDirty : function () {
			var changedFeed = this.form.af_isDirty();
			return changedFeed;
		},

		umescapeHtmlText : function (text) {
			return jQuery("<div/>").html(text).text()
		}

	};

	jQuery.fn.commentForm = function(options) {
		return this.each(function() {
			var element = jQuery(this);
			// Return early if this element already has a plugin instance
			if (element.data('commentForm')) {
				return;
			}
			// Store plugin object in this element's data
			element.data('commentForm', new CommentForm(this, jQuery.extend({}, options)));
		});
	};
})();
//
////
