/* MESSENGER
***************************************************************************************************/
var Messenger = Class.create(
{
	initialize: function(element, messageContainerId)
	{
		this.messagesBoxId = messageContainerId;
		this.element = element;
		this.types = {error: 0, warning: 1, message: 2};
		this.msgStyles = ['msg-error', 'msg-warning', 'msg-message'];
		this.hasEroors = false;
		this.hasWarnings = false;
	},

	show: function()
	{
		$(this.messagesBoxId).setStyle({display: 'block'});
		// Element.scrollTo(this.messagesBoxId);
		// setTimeout('smoothShow("' + this.messagesBoxId + '")', 102000);
	},

	hide: function()
	{
		$(this.messagesBoxId).setStyle({display: "none"});
	},

	addMessages: function(messages)
	{
		var messagesText = "";
		for (var i=0; i<messages.length; i++){
			messagesText += '<p class=\'' + this.msgStyles[messages[i][1]] + '\'>' + messages[i][0] + '</p>';
			if(messages[i][1] == 0){
				this.hasErrors = true;
				this.element.fire('Messenger:throwError');
			} else if(messages[i][1] == 1) {
				this.hasWarnings = true;
				this.element.fire('Messenger:throwWarning');
			}
		}
		$(this.messagesBoxId).update(messagesText);
	},

	addMessage: function(text, messageType)
	{
		text += '<p class=\'' + this.msgStyles[messageType] + '\'>' + text + '</p>';
		if(messageType == 0){
			this.hasErrors = true;
			this.element.fire('Messenger:throwError');
		} else if(messageType == 1) {
			this.hasWarnings = true;
			this.element.fire('Messenger:throwWarning');
		}
		$(this.messagesBoxId).update(messagesText);
	},

	addLoadingMessage: function()
	{
		$(this.messagesBoxId).update('<p class="msg-loading">Выполняется отправка данных</p>');
		this.show();
	}
});
ScriptsManager.registerScript("Messenger");


/* UPDATE TRANSACTIONS COUNTER
***************************************************************************************************/
var UpdateTransactionsManager = Class.create({
	initialize: function(element)
	{
		this.element = element;
		this.openTransactions = new Hash();
		this.hasActive = false;
	},

	_complete: function()
	{
		this.element.fire('UpdateTransactionsManager:transactionsComplete');
	},

	add: function(id, value)
	{
		this.openTransactions.set(id, value);
		this.hasActive = true;
		this.element.fire('UpdateTransactionsManager:startTransaction');
	},

	remove: function(id)
	{
		this.openTransactions.unset(id);
		this.element.fire('UpdateTransactionsManager:finishTransaction', {id: id});
		if(this.openTransactions.keys().length == 0){
			this.hasActive = false;
			this._complete();
		}
	},
	
	clear: function()
	{
		this.openTransactions = new Hash();
		this.hasActive = false;		
		this._complete();
	}
});
ScriptsManager.registerScript("UpdateTransactionsManager");

/* COMMENT LINE
***************************************************************************************************/
var CommentLine = Class.create(
{
//
// Constructor
//
	initialize: function(ident, idParent, addActionUrl, editActionUrl, deleteActionUrl, getPageActionUrl, pagerUrlVarName, permissions)
	{
	//{ Fields
		this.container = $(ident + 'comment-line-container');
		this.htmlIdent = ident;
		this.idParent = idParent;
		this.controlManager = pageControlsManager;
		this.permissions = permissions;

		this.addActionUrl = addActionUrl;
		this.editActionUrl = editActionUrl;
		this.deleteActionUrl = deleteActionUrl;
		this.getPageActionUrl = getPageActionUrl;

		this.content = "";

		var containers = $$('.discuss-container');
		var loaders = $$('.discuss-loader');
		for(var i = 0; i < containers.length; i++) {
			if (this.container.descendantOf(containers[i])) {
				for(var j = 0; j < loaders.length; j++) {
					if (loaders[j].descendantOf(containers[i])) {
						this._loader = loaders[j];
						break;
					}
				}
				break;
			}
		}

		this.transactions = new RequestTransactionsManager(this.container);
		//this._messenger = new Messenger(this.container, 'comment-line-messages');
	//}
	//{ Objects
		//{ Add form
			this._addFormContainer = $(this.htmlIdent + "comment-line-addform");
			if(permissions.addition){
				this._addForm = new CommentLineAddForm(this, this._addFormContainer, this.addActionUrl, new Hash({id_parent: this.idParent}));
			// Events
				Event.observe(this._addFormContainer, "AddForm:addButtonClick", function(){this._onAddButtonClick()}.bind(this));
				Event.observe(this._addFormContainer, "AddForm:sendRequest", function(e){this.transactions.add()}.bind(this));
				Event.observe(this._addFormContainer, "AddForm:receiveResponse", function(e){
					this.transactions.remove();
					this._refresh(this._addForm.responseText);
				}.bind(this));
			}
		//}

		//{ Comments
			this._comments = null;
			this._commentsContainer = $(this.htmlIdent + 'comment-line-container');
			this.updations = new RequestTransactionsManager(this._commentsContainer);
			this.editedComments = new UpdateTransactionsManager(this._commentsContainer);
			this._registerComments();
		//}

		//{ Pager
			var createPagerHandler = function(){
				this._pager = new Pager(this, this.htmlIdent + "comment-line-pager", this.getPageActionUrl, new Hash({id_parent: this.idParent}), pagerUrlVarName, "div#"+ this.htmlIdent + "comment-line-pager");
				this._observeToPager();
			}.bind(this);
			ScriptsManager.scriptIsReady("Pager", createPagerHandler);
		//}
	//}
	//{ Observing to events
		//Transactions
		Event.observe(this.container, 'RequestTransactionsManager:transactionsComplete', function(){/*this._messenger.hide(); this.unblock()*/}.bind(this));
		Event.observe(this.container, 'RequestTransactionsManager:startTransaction', function(){ /*this._messenger.addLoadingMessage(); this.block();*/}.bind(this));
	//}
	},
//
//{  INNER METHODS
//
//{ Creating
	_createComments: function()
	{
		if(this.permissions.edition || this.permissions.deletion){
			var destroy = function(pair){
				pair.value.destroy();
			}.bind(this);
			this._comments.each(destroy);
			this.controlManager.registerElements(new PageControlType("div#" + this.htmlIdent + "comment-line-container a.button", "AJsButton"));
			this._registerComments();
		}
	},

	_registerComments: function()
	{
		if(this.permissions.edition || this.permissions.deletion){
			this._comments = new Hash();
			var containers = $$("div#" + this.htmlIdent + "comments div.commentline-item");
			var id;
			for(var i=0; i<containers.length; i++){
				id = containers[i].id.replace(this.htmlIdent + "comment-line-item", "");
				this._comments.set(id, new CommentLineComment(this, id, containers[i], this.editActionUrl, this.deleteActionUrl, new Hash({id_parent: this.idParent}), this.permissions));
				Event.observe(containers[i], "Comment:open", function(e){this.editedComments.add(e.memo.comment.id, e.memo.comment)}.bind(this));
				Event.observe(containers[i], "Comment:finishEdition", function(e){this.editedComments.remove(e.memo.comment.id)}.bind(this));
				Event.observe(containers[i], "Comment:receiveResponse", function(e){
					this.updations.remove();
					if(e.memo.comment.isOpened){
						this.editedComments.add(e.memo.comment.id, e.memo.comment);
					}
				}.bind(this));
				Event.observe(containers[i], "Comment:sendRequest", function(e){
					this.updations.add()
					this.editedComments.remove(e.memo.comment.id);
				}.bind(this));
			}
		}
	},

//}
//{ Blocking
	block: function()
	{
		return false;
	},

	unblock: function()
	{
		return false;
	},

	_blockComments: function()
	{
		if(this._comments != null){
			var blockCommentHandler = function(item){
				item.value.block();
			};
			this._comments.each(blockCommentHandler);
		}
	},
//}

//{ User requests
	_requestForSavingData: function()
	{
		if(this.editedComments.hasActive){
			var userConfirm = confirm("На странице есть несохраненные комментарии.\n Сохранить их?");
			if (userConfirm){
				this._saveOpenedComments();
			} else {
				return false;
			}
		}
		return true;
	},
//}

//{ Data
	_saveOpenedComments: function()
	{
		var saveHandler = function(item){
			item.value.updateComment();
		}

		this.editedComments.openTransactions.each(saveHandler);
	},

	_refresh: function(content)
	{
		var refreshHandler = function(){
			Event.stopObserving(this.container,'RequestTransactionsManager:transactionsComplete');
			Event.stopObserving(this._commentsContainer,'RequestTransactionsManager:transactionsComplete');

			Element.removeClassName(this.container.parentNode.parentNode, 'hidden-block');

			this._commentsContainer.update(content);
			this._createComments();
			this._pager.createControls();
			this._observeToPager();
			this.editedComments.clear();
			this._loader.addClassName('hidden-block');
		}.bind(this);

		if(this.transactions.hasActive){
			Event.observe(this._commentsContainer,'RequestTransactionsManager:transactionsComplete', refreshHandler);
		} else if(this.updations.hasActive){
			Event.observe(this.container,'RequestTransactionsManager:transactionsComplete', refreshHandler);
		} else {
			refreshHandler();
		}
	},
//}
//}


//
//{ Events handlers
//
	//{ Page button click
	_observeToPager: function()
	{
		Event.observe(this._pager.container, 'Pager:buttonClick', function(e){
			this._onPagerButtonClick()}.bind(this));
		Event.observe(this._pager.container, 'Pager:sendRequest', function(e){
			this.transactions.add();
			this._loader.removeClassName('hidden-block');
			//this._messenger.addLoadingMessage();
		}.bind(this));
		Event.observe(this._pager.container, 'Pager:receiveResponse', function(e){
			this.transactions.remove();
			this._refresh(this._pager.content);
		}.bind(this));
		Event.observe(this._pager.container, 'Pager:transactionsComplete', function(e){
			//this._messenger.hide();
		}.bind(this));
	},

	_onPagerButtonClick: function()
	{
		if(this.editedComments.hasActive && this._requestForSavingData()){
			var getPageHandler = function(){
				Event.stopObserving(this._commentsContainer,'UpdateTransactionsManager:transactionsComplete', getPageHandler);
				this._pager.sendRequest();
				this._blockComments();
			}.bind(this);
			Event.observe(this._commentsContainer,'UpdateTransactionsManager:transactionsComplete', getPageHandler);
		} else {
			this._pager.sendRequest();
			this._blockComments();
		}
	},
	//}
	//{ Add button click
	_onAddButtonClick: function()
	{
		this._addForm.addComment();
	},
	_onAddFormReceiveResponse: function()
	{
		this.transactions.remove();
		this._refresh(this._addForm.responseText);
	},
	//}
//}

	setIdParent: function(idParent)
	{
		if(this.editedComments.hasActive && this._requestForSavingData()){
			var getPageHandler = function(){
				Event.stopObserving(this._commentsContainer,'UpdateTransactionsManager:transactionsComplete', getPageHandler);
				this._setParent(idParent);
				this._blockComments();
			}.bind(this);
			Event.observe(this._commentsContainer,'UpdateTransactionsManager:transactionsComplete', getPageHandler);
		} else {
			this._setParent(idParent);
			this._blockComments();
		}
	},


	_setParent: function(idParent)
	{
		this.idParent = idParent;

		if(this.permissions.addition) {
			this._addForm.params = new Hash({id_parent: this.idParent});
		}

		this._pager.params = new Hash({id_parent: this.idParent});
		this._pager.sendStaticRequest(1);
	}
});
ScriptsManager.registerScript("CommentLine");

/* COMMENTLINE ADDFORM
***************************************************************************************************/
var CommentLineAddForm = Class.create(
{
//{ Constructor
	initialize: function(owner, container, addRequestUrl, requestParams)
	{
		this.owner = owner;
		this.container = container;
		this.addRequestUrl = addRequestUrl;
		this.params = requestParams;
		this.controlManager = owner.controlManager;
		this.responseText = null;
		this.htmlIdent = owner.htmlIdent;
		this.form = $(this.htmlIdent + "discussform");

		this._messenger = new Messenger(this.container, 'discuss-form-messages');

		this._onFailureHandler = owner._onFailureHandler;
		this._editor = null;
	//{ Controls
		this._addButton = this.controlManager.getControls($(this.htmlIdent + "comment-line-add-button"));

		Event.observe(window, 'load', function(){
				this._addButton.setStatus(this._addButton.statuses.clear);
		}.bind(this))
	//}
	//{ Observing
		Event.observe(this._addButton.element, 'Control:click', function(e){ this._onAddButtonClick() }.bind(this));
	//}
	},
//}
//{ Public methods
	block: function()
	{
		this.form.disable();
	},

	unblock: function()
	{
		this.form.enable();
		this._addButton.setStatus(this._addButton.statuses.clear);
	},

	hide: function()
	{
		this.container.hide();
	},

	show: function()
	{
		this.container.show();
	},

//{ Requests
	//{ Add comment
	addComment: function()
	{
		var requestParams = new Hash(Form.serialize(this.form, true));
		requestParams = requestParams.merge(this.params);
		this.block();
		this._messenger.addLoadingMessage();
		this._messenger.show();

		var onSuccessHandler = function(transport, json) {
			if (json == null) {
				showFatalError(transport.responseText);
			} else if(json.messages.length != 0) {
				this._messenger.addMessages(json.messages);
				this._messenger.show(json.messages);
			}
			this.responseText = transport.responseText;
			this.unblock();
			this.container.fire("AddForm:receiveResponse", {comment: this});
		}.bind(this);

		this.container.fire("AddForm:sendRequest");
		new Ajax.Request(this.addRequestUrl, {
			parameters: requestParams.toQueryString(),
			onSuccess: onSuccessHandler,
			onFailure: function(){
				this.container.fire("AddForm:receiveResponse", {comment: this});
				this._onFailureHandler();
			}
		});
	},
	//}
//}
//}

//{ Private methods
	_onAddButtonClick: function()
	{
		this.container.fire("AddForm:addButtonClick", {comment: this});
		this._addButton.setStatus(this._addButton.statuses.active);
	}
//}
});
ScriptsManager.registerScript("CommentLineAddForm");

/* COMMENTLINE COMMENT
***************************************************************************************************/
var CommentLineComment = Class.create(
{
//{ Constructor
	initialize: function(owner, id, container, updateRequestUrl, deleteRequestUrl, requestParams, permissions)
	{
		this.owner = owner;
		this.container = container;
		this.updateRequestUrl = updateRequestUrl;
		this.deleteRequestUrl = deleteRequestUrl;
		this.params = requestParams;
		this.controlManager = owner.controlManager;
		this.responseText = null;
		this.oldText = null;
		this.htmlIdent = owner.htmlIdent;
		this.id = id;
		this.isOpened = false;
		this._editor = this.container.select("form textarea.text")[0];
		this._editForm = this.container.select("form")[0];
		this._textContainer = this.container.select("div.discuss-item-text")[0];

		this._messenger = new Messenger(this.container, 'comment-line-item-messages' + id);

		this._activeButton = null;
		this._controls = new Array();
		this._onFailureHandler = owner._onFailureHandler;

	//{ Controls
		if(permissions.edition){
			//this._editButton = this.controlManager.getControls(this.htmlIdent + "comment-line-item-button-edit" + this.id);
			this._editButton = this.controlManager.getControls(this.container.select("a.edit")[0]);

			this._editButton.setStatus(this._editButton.statuses.clear);
			this._cancelButton = this.controlManager.getControls(this.container.select("a.cancel")[0]);
			this._cancelButton.element.removeClassName('hidden');
			this._cancelButton.setStatus(this._cancelButton.statuses.hidden);
			this._updateButton = this.controlManager.getControls(this.container.select("a.update")[0]);
			this._updateButton.element.removeClassName('hidden');
			this._updateButton.setStatus(this._updateButton.statuses.hidden);
			Event.observe(this._editButton.element, 'Control:click', function(e){ this._onEditButtonClick() }.bind(this));
			Event.observe(this._cancelButton.element, 'Control:click', function(e){ this._onCancelButtonClick() }.bind(this));
			Event.observe(this._updateButton.element, 'Control:click', function(e){ this._onUpdateButtonClick() }.bind(this));
		}

		if(permissions.deletion){
			this._deleteButton = this.controlManager.getControls(this.container.select("a.delete")[0]);
			this._deleteButton.setStatus(this._deleteButton.statuses.clear);
			Event.observe(this._deleteButton.element, 'Control:click', function(e){ this._onDeleteButtonClick() }.bind(this));
		}
	//}
	},
//}
//{ Public methods
	block: function()
	{
		this._deleteButton.setStatus(this._deleteButton.statuses.disabled);
		if(this.isOpened){
			this._cancelButton.setStatus(this._cancelButton.statuses.disabled);
			this._updateButton.setStatus(this._updateButton.statuses.disabled);
			this._editor.disable();
		} else {
			this._editButton.setStatus(this._editButton.statuses.disabled);
		}
	},

	unblock: function()
	{
		this._deleteButton.setStatus(this._deleteButton.statuses.clear);
		if(this.isOpened){
			this._cancelButton.setStatus(this._cancelButton.statuses.clear);
			this._updateButton.setStatus(this._updateButton.statuses.clear);
			this._editor.enable();
		} else {
			this._editButton.setStatus(this._editButton.statuses.clear);
		}
	},

	hide: function()
	{
		this.container.hide();
	},

	show: function()
	{
		this.container.show();
	},

	destroy: function()
	{
		this.controlManager.destroyControls(this._updateButton);
		this.controlManager.destroyControls(this._editButton);
		this.controlManager.destroyControls(this._cancelButton);
		this.controlManager.destroyControls(this._deleteButton);
	},

//{ Requests
	//{ Update comment
	updateComment: function()
	{
		this._deleteButton.setStatus(this._deleteButton.statuses.disabled);
		this._cancelButton.setStatus(this._cancelButton.statuses.disabled);
		this._updateButton.setStatus(this._updateButton.statuses.active);
		this._editor.disable()
		this._messenger.addLoadingMessage();

		var onSuccessHandler = function(transport, json) {
			if (json == null) {
				showFatalError(transport.responseText);
			} else {
				this.responseText = transport.responseText;
				if(json.messages.length != 0) {
					this._messenger.addMessages(json.messages);
					this.unblock();
					if(!this._messenger.hasErrors){
						var text = this._editor.getValue().replace(/\n/gi, "<br />").strip();
						this._textContainer.update(text);
						this._closeComment();
						this._messenger.hide();
					}
				} else {
					this._closeComment();
				}
			}
			this.container.fire("Comment:receiveResponse", {comment: this});
		}.bind(this);


		var params = this.params;
		params.set('id_comment', this.id);
		params.set('text', this._editor.getValue());
		this.container.fire("Comment:sendRequest", {comment: this});
		new Ajax.Request(this.updateRequestUrl, {
			parameters: params.toQueryString(),
			onSuccess: onSuccessHandler,
			onFailure: function(){
				this.container.fire("Comment:receiveResponse", {comment: this});
				this._onFailureHandler();
			}
		});
	},
	//}
	//{ Delete comment
	deleteComment: function()
	{
		//this._messenger.addMessage("Выполняется удаление");
		//this.messenger.show();
		this._deleteButton.setStatus(this._deleteButton.statuses.active);
		if(this.isOpened){
			this._editButton.setStatus(this._editButton.statuses.clear);
		} else {
			this._cancelButton.setStatus(this._cancelButton.statuses.clear);
			this._updateButton.setStatus(this._updateButton.statuses.clear);
		}

		this.hide();
		var onSuccessHandler = function(transport, json) {
			if (json == null) {
				showFatalError(transport.responseText);
			} else if(json.messages.length != 0) {
				this._messenger.addMessages(json.messages);
				if(this._messenger.hasErrors){
					this._messenger.show();
					this._showComment(idComment);
				}
			}
			this.content = transport.responseText;
			this.container.fire("Comment:receiveResponse", {comment: this});
		}.bind(this);

		var params = this.params;
		params.set('id_comment', this.id);
		this.container.fire("Comment:sendRequest", {comment: this});
		new Ajax.Request(this.deleteRequestUrl, {
			parameters: params.toQueryString(),
			onSuccess: onSuccessHandler,
			onFailure: function(){
				this.container.fire("Comment:receiveResponse", {comment: this});
				this._onFailureHandler();
			}
		});
	},
	//}
//}
//}

//{ Private methods
	_onEditButtonClick: function()
	{
		this.container.fire("Comment:open", {comment: this});
		this._editButton.setStatus(this._editButton.statuses.active);
		this._openComment();
	},

	_onDeleteButtonClick: function()
	{
		var userConfirm = confirm("Вы действительно хотите удалить коментарий?");
		if (userConfirm){
			this.container.fire("Comment:delete", {comment: this});
			this.deleteComment();
		}
	},

	_onCancelButtonClick: function()
	{
		this.container.fire("Comment:cancel", {comment: this});
		this._cancelButton.setStatus(this._cancelButton.statuses.active);		
		this._closeComment();
	},

	_onUpdateButtonClick: function()
	{
		this.container.fire("Comment:submit", {comment: this});
		this.updateComment();
	},

	_openComment: function()
	{
		Element.setStyle(this._textContainer, {display: "none"});
		this._editor.setValue(this._textContainer.innerHTML.replace(/<br\s*\/{0,1}>\s*/gi, "\n").strip());		
		this._editForm.setStyle({display: "block"});
		this._editButton.setStatus(this._editButton.statuses.hidden);
		this._updateButton.setStatus(this._updateButton.statuses.clear);
		this._cancelButton.setStatus(this._cancelButton.statuses.clear);
		this.isOpened = true;
		this.container.fire("Comment:startEdition", {comment: this});
	},

	_closeComment: function()
	{
		this._messenger.hide();
		this._editButton.setStatus(this._editButton.statuses.clear);
		this._deleteButton.setStatus(this._deleteButton.statuses.clear);
		this._cancelButton.setStatus(this._cancelButton.statuses.hidden);
		this._updateButton.setStatus(this._updateButton.statuses.hidden);
	
		this._editForm.setStyle({display: "none"});
		this._textContainer.setStyle({display: "block"});
		this.isOpened = false;
		this.container.fire("Comment:finishEdition", {comment: this});
	}
//}
});
ScriptsManager.registerScript("CommentLineComment");
