// JavaScript Document

document.writeln('<script language="javascript" type="text/javascript" src="/js/utf8.js"></script>');
document.writeln('<script language="javascript" type="text/javascript" src="/js/property_monitor.js"></script>');
document.writeln('<script language="javascript" type="text/javascript" src="/js/draggable.js"></script>');

PeriodicalRequest = Class.create({
		initialize: function (url, options)
		{
			//$super(url, options);
			
			this.dataStr = null;
			this.request = null;
			this.requestUrl = url;
			this.requestOptions = null;
			this.timer = null;
			this.options = options;
			this.frequency = (options.frequency != null)? options.frequency: 2; // number of seconds delay between requests - default 2
			this.currentFrequency = this.frequency;
			this.decay = (options.decay != null)? options.decay: 1; // decay multiplier - default 1 (no decay)
			this.decayLimit = (options.decayLimit != null)? options.decayLimit: 15; // decay limit prevents frequency from exceeding limit - default 15 seconds
			this.stopped = false;
			
			this.requestOptions = Object.clone(this.options);
			this.requestOptions.onSuccess = this.handleRequestSuccess.bind(this);
			this.requestOptions.onFailure = this.handleRequestFailure.bind(this);
			
			this.createTimer();
		},
		createTimer: function()
		{
			if(!this.stopped) {
				this.handleTimerComplete.bind(this).delay(this.currentFrequency);
			}
		},
		handleTimerComplete: function ()
		{
			this.request = new Ajax.Request(this.requestUrl, this.requestOptions);
		},
		handleRequestSuccess: function (response)
		{
			// chech response data compared to last and if same then apply decay and recreate timer
			if(response.responseText == this.dataStr) {
				this.currentFrequency = (this.currentFrequency * this.decay <= this.decayLimit)? this.currentFrequency * this.decay: this.decayLimit;
			}
			else { 
				this.currentFrequency = this.frequency; 
				this.options.onSuccess(response); // call the configured request success handler
			}
			
			this.dataStr = response.responseText; // set the data string for next request check
			this.createTimer(); // initiate next request
	
		},
		handleRequestFailure: function (response)
		{
			this.options.onFailure(response);
		},
		forceRequest: function()
		{
			this.handleTimerComplete();
		},
		resetDecay: function()
		{
			this.currentFrequency = this.frequency;
		},
		start: function ()
		{
			this.stopped = false;
		},
		stop: function ()
		{
			this.stopped = true;
		}
	})

SupportChat = Class.create({
		initialize: function ()
		{
			// vars
			this.periodical = null;
			this.container = null;
			this.support = null;
			this.msgWindow = null;
			this.msgInput = null;
			this.msgInputDefault = null;
			this.msgSendButton = null;
			this.msgTemplate = new Template('<div class="message #{msgType}-message"><label class="name">#{msgAuthor}:</label><div class="text">#{msgText}</div><div class="clear"></div></div>');
			this.msgTypes = { agent:"csr", user:"usr", system:"sys", error:"err" };
			this.relativeChatPosition = null;
			this.lastScrollOffsets = null;
			this.activeChatCloseButton = null;
			this.dragBar = null;
			this.updateChatPositionHandler = this.updateActiveChatPosition.bind(this);
			this.active = false;
			this.monitor = null;
			this.dragger = null;

			document.observe("dom:loaded", this.handleDomLoaded.bind(this));
		},
		handleDomLoaded: function (evt)
		{
			this.container = $('SupportCtnr');
			this.support = $('Support');
			this.msgWindow = $('SupportMsgWindow');
			this.msgInput = $('SupportMsgInput');
			this.msgInputDefault = $('SupportDefaultMsgInputContent');
			this.msgSendButton = $('SupportSendButton');
			this.activeChatCloseButton = $('SupportClose');
			this.dragBar = $('SupportMove');
			
			
			this.msgInput.value = this.msgInputDefault.value;
			
			this.addEventListeners();
			
			var requestOptions = {}
			requestOptions.onSuccess = this.handlePeriodicalRequestSuccess.bind(this);
			requestOptions.onFailure = this.handlePeriodicalRequestFailure.bind(this);
			requestOptions.decay = 2;
			requestOptions.decayLimit = 10;
			
			this.periodical = new PeriodicalRequest("/b3wchat/chatActions.asp?action=get", requestOptions);
			//this.periodical.stop(); // remove line when finished development
		},
		addEventListeners: function ()
		{
			this.msgInput.observe("focus", this.handleInputFocus.bind(this));
			this.msgInput.observe("blur", this.handleInputBlur.bind(this));
			this.msgInput.observe("keyup", this.handleInputKeyUp.bind(this));
			this.msgSendButton.observe("click", this.handleMessageSend.bind(this));
			this.activeChatCloseButton.observe("click", this.deactivate.bind(this));
			this.dragBar.observe("mousedown", this.clearFlash.bind(this));
		},
		clearFlash: function()
		{
			this.dragBar.removeClassName("flash");
		},
		handlePeriodicalRequestSuccess: function (response)
		{
			var rObj = response.responseText.evalJSON(false);
			if(rObj.error != null && rObj.error == "true") {
				this.showErrorMessage(rObj.errorMsg);
			}
			else {
				if(rObj.msgList.length > 0) {
					this.activate();
					
					var historyChanged = false;
					//alert(this.msgWindow.childNodes);
					if(this.msgWindow.childNodes != undefined) {
						for(var i=0; i < this.msgWindow.childNodes.length; i++) {
							//alert(this.msgWindow.childNodes[i].childNodes[1].innerHTML + " =? " + rObj.msgList[i].msg);
							if(this.msgWindow.childNodes[i].childNodes[1].innerHTML != rObj.msgList[i].msg) {
								historyChanged = true;
								break;
							}
						}
					}
					
					if(historyChanged) { // if message history is different to the msgWindow display then redraw all messages.
						this.clearMessageWindow();
						rObj.msgList.each(this.addMessage.bind(this));
					}
					else { // otherwise just add new messages.
						currentMsgCount = (this.msgWindow.childNodes != undefined)? this.msgWindow.childNodes.length: 0;
						for(var i = currentMsgCount; i < rObj.msgList.length; i++) {
							this.addMessage(rObj.msgList[i]);
						}
					}
					
					// if message is from the agent then flash the drag bar.
					if(rObj.msgList[rObj.msgList.length - 1].type == "AgName") {
						this.dragBar.addClassName("flash");
					}
				}
			}
		},
		handlePeriodicalRequestFailure: function (response)
		{
			this.showErrorMessage(response.responseText);
		},
		clearMessageWindow: function()
		{
			this.msgWindow.scrollTop = 0;
			this.msgWindow.innerHTML = "";
		},
		activate: function()
		{
			if(!this.active) {
				// activate message session and set display mode back to absolute
				this.support.addClassName('active');
				//this.support.absolutize();
				this.support.style.position = "absolute";
				document.body.appendChild(this.support);
				
				this.active = true;
				
				this.updateActiveChatPosition();
				
				this.monitor = new PropertyMonitor(document.viewport.getScrollOffsets, 0.2, this.updateChatPositionHandler);
				Event.observe(window, "resize", this.updateChatPositionHandler);
				this.dragger = new Draggable(this.support, $('SupportMove'), this.updateChatPositionHandler);
			}
		},
		deactivate: function() 
		{
			if(this.active) {
				this.clearFlash();
				
				this.monitor.stop();
				this.dragger.stop();
				Event.stopObserving(window, "resize", this.updateChatPositionHandler);
				
				this.clearMessageWindow();
				
				this.container.appendChild(this.support);
				this.support.style.left = "";
				this.support.style.top = "";
				this.support.style.position = "relative";
				this.support.removeClassName('active');
				this.active = false;
				
				this.relativeChatPosition = null;
				this.lastScrollOffsets = null;
				
				var post = new Ajax.Request("/b3wchat/chatActions.asp?action=close", {});
				
				this.msgInput.value = this.msgInputDefault.value;
			}
		},
		updateActiveChatPosition: function()
		{
			if(this.active) {
				var scrollOffset = document.viewport.getScrollOffsets();
				
				if(this.relativeChatPosition == null) {
					this.lastScrollOffsets = scrollOffset;
					var leftOffset = (document.viewport.getWidth() - this.support.offsetWidth) / 2;
					var topOffset = (document.viewport.getHeight() - this.support.offsetHeight - 5);
					this.relativeChatPosition = {x: leftOffset, y: topOffset};
				}
				else {
					var leftOffset = this.support.offsetLeft - this.lastScrollOffsets.left;
					var topOffset = this.support.offsetTop - this.lastScrollOffsets.top;
					
					// adjust position so it falls inside visible screen area.
					if(leftOffset > document.viewport.getWidth() - this.support.offsetWidth)
						leftOffset = document.viewport.getWidth() - this.support.offsetWidth - 5;
						
					if(topOffset > document.viewport.getHeight() - this.support.offsetHeight)
						topOffset = document.viewport.getHeight() - this.support.offsetHeight - 5;
						
					if(leftOffset < 5) leftOffset = 5;
					
					if(topOffset < 5) topOffset = 5;
					
					this.relativeChatPosition = {x: leftOffset, y: topOffset};
				}
				
				this.support.style.left = Number.toCssString(this.relativeChatPosition.x + scrollOffset.left);
				this.support.style.top = Number.toCssString(this.relativeChatPosition.y + scrollOffset.top);
				
				this.lastScrollOffsets = scrollOffset;
			}
		},
		addMessage: function(msgObj)
		{
			this.activate();
			
			msgTemplateObj = {}
			
			msgTemplateObj.msgType = (msgObj.type == "AgName")? (msgObj.name == "")? this.msgTypes.system: this.msgTypes.agent: this.msgTypes.user;
			msgTemplateObj.msgAuthor = msgObj.name;
			msgTemplateObj.msgText = Utf8.decode(msgObj.msg);
			
			this.msgWindow.innerHTML += this.msgTemplate.evaluate(msgTemplateObj);
			this.scrollLastMessageIntoView();
		},
		showErrorMessage: function(msg)
		{
			this.activate();
			
			msgTemplateObj = {}
			
			msgTemplateObj.msgType = this.msgTypes.error;
			msgTemplateObj.msgAuthor = "";
			msgTemplateObj.msgText = msg;
			
			this.msgWindow.innerHTML += this.msgTemplate.evaluate(msgTemplateObj);
			this.scrollLastMessageIntoView();
		},
		scrollLastMessageIntoView: function()
		{
			if(this.msgWindow.scrollTop != this.msgWindow.scrollHeight) {
				this.msgWindow.scrollTop = this.msgWindow.scrollHeight;
			}
		},
		handleInputFocus: function (evt)
		{
			if(this.msgInput.value == this.msgInputDefault.value) {
				this.msgInput.value = "";
			}
			this.clearFlash();
		},
		handleInputBlur: function (evt)
		{
			if(this.msgInput.value == "" && !this.active) {
				this.msgInput.value = this.msgInputDefault.value;
			}
		},
		handleInputKeyUp: function (evt)
		{
			if(evt.keyCode == 13) {
				this.handleMessageSend(null);
			}
		},
		handleMessageSend: function (evt)
		{
			if(this.msgInput.value != this.msgInputDefault.value && this.msgInput.value != "") {
				var requestOptions = {}
				requestOptions.onSuccess = this.handleSendRequestSuccess.bind(this);
				requestOptions.onFailure = this.handleSendRequestFailure.bind(this);
				requestOptions.parameters = {SendText: this.msgInput.value + " "};
				requestOptions.method = "post";
			
				var post = new Ajax.Request("/b3wchat/chatActions.asp?action=send", requestOptions);
				
				this.msgInput.value = "";
				this.msgInput.focus();
				
				this.periodical.forceRequest();
				this.periodical.resetDecay();
			}
		},
		handleSendRequestSuccess: function (response)
		{
			var rObj = response.responseText.evalJSON(false);
			if(rObj.error != null && rObj.error == "true") {
				this.showErrorMessage(rObj.errorMsg);
			}
		},
		handleSendRequestFailure: function (response)
		{
			this.showErrorMessage("Error sending last message. Erreur envoyer la derniere message.");
		}
	});

chat = new SupportChat();