﻿String.prototype.format = function() {
  var s = this;
  for (var i = 0; i < arguments.length; i++) {       
    var reg = new RegExp("\\{" + i + "\\}", "gm");  
    s = s.replace(reg, arguments[i]);
  }

  return s;
};

// TODO:
// - avoid multiple calls to crossdomain.xml (because each request uses a new instance of Xhr)
// - "new session" button
// - test with other browsers (Safari, Opera)
// - test from mobile phone
// - minimize and obfuscate the code

(function($) {
    var Livechat = function(element, config) {
        var elem = $(element);
        var obj = this;
        var errorSleepTime = 500;
        var refreshXhr;

        // Get the value of the session cookie.
        function getXsrf() {
            return null;
        
            var r = document.cookie.match("\\b_xsrf=([^;]*)\\b");
            return r ? r[1] : undefined;
        };

        // Handler of the key press event.
        function keyPress(e) {
            var el = $("#{0}-text".format(element.id));
            switch (e.keyCode) {
                case 13: return receive();
                case 10: return receive(); // iPhone enter key
            }

            return true;
        }

        // Clear the chat history.
        function clearHistory() {
            $('#{0}-history-table tr'.format(element.id)).remove();
        }

        // Append a new message to the chat history and scroll to the bottom.
        function appendMsg(msg) {
            var table = $('#{0}-history-table'.format(element.id));
            table.append(msg);

            var e = $('#{0}-history'.format(element.id));
            e.animate({ 
                easing: 'swing',
                scrollTop: e[0].scrollHeight
            }, 200);
        }

		function replaceSender(nick) {
			if(nick == 'customer') return 'Tu';
			if(nick == 'operator') return 'Travel Cyborg';
			return nick;
		}
		
        // Add a new chat message.
        function addChatMsg(msg) {
            var sender = replaceSender(msg.attrs.nick);
			var div = '<tr id="livechat-history-msg">';
            div +=      '<td width="100%">';
            div +=          '<span id="livechat-history-sender-{1}">{0}: </span>'.format(sender,msg.attrs.nick);
			div +=          '<span id="livechat-history-text">{0}</span>'.format(msg.body);
            div +=      '</td>';
            div +=    '</tr>';
            appendMsg(div);
        }
        
        // Add a new info chat message.
        function addInfoMsg(msg) {
            var div = '<tr class="livechat-history-msg livechat-history-info">';
            div +=      '<td colspan="2" width="100%">{0}</td>'.format(msg.body);
            div +=    '</tr>';
            appendMsg(div);
        }

		function checkOutput(msg) {
			var begin = msg.indexOf("<!--");
			var end = msg.indexOf("-->");
			var ret="";
			if (begin>=0 && end >0)
			{
				ret = msg.substring(begin,end);
			}else
			{
				ret ="-1";
			}
			return ret;
		}
		
        // Flensed XmlHttpRequest wrapper.
        function Xhr(args) {
            if (!args) throw "Parameter args of method Xhr cannot be empty";
            if (!args.url) return;
            if (!args.type) args.type = "GET";
            if (!args.success) args.success = function() { };
            if (!args.error) args.error = function() { };
        
            var xhr = new flensed.flXHR();
            if (args.policyUrl) xhr.loadPolicyURL = args.policyUrl;
            xhr.onerror = args.error;
            xhr.onreadystatechange = function(obj) {
                if (obj.readyState == 4) {
                    args.success(obj.responseText, obj);
                }
            };

            xhr.open(args.type, args.url);
            if (!args.data)
                xhr.send();
            else {
                var body = "";
                for (var i in args.data) {
                    if (body.length > 0) body += "&";
                    body += "{0}={1}".format(i, args.data[i]);
                }
                
                xhr.send(body);
            }
            
            return xhr;
        }

        // Start a new chat session and get the token (the token is not used).
        function token(fn) {
            if (!fn) success = function() { };

            if (refreshXhr != null) {
                refreshXhr.abort();
                refreshXhr = null;
            }
            
            Xhr({
                url: config.baseUrl + config.domainMethods + '/token',
                policyUrl: config.baseUrl + config.policyPath,
                type: 'POST',
                data: { fresh: true, opener: null, _xsrf: getXsrf() },
                success: function() {
                    // Clear the chat history.
                    clearHistory();
                    fn();
                },
                error: function() { }
            });
        }
    
        function refreshSuccess(data) {
            var messages = eval("(" + data + ")");
            $.each(messages, function(i, msg) {
                switch (msg.type) {
                    case 'chat':
						//alert('chat');
						//alert(msg);
						addChatMsg(msg);
                        break;
                    case 'info':
						//alert('info');
                        addInfoMsg(msg);
                        break;
					case 'search':
						//alert('search');
						//alert(msg.body);
						goToSerp(msg);
						break;
                }
            });
			setScrollHistoryVisible();
            errorSleepTime = 500;
            setTimeout(refresh, 0);
        }

		function setScrollHistoryVisible(){
			$('#livechat-history').css('overflow-y','scroll');
		}
		
		// Post message to the SERP page.
        function goToSerp(msg) {
            if (!msg) return;

            var url = "http://confronta.europelowcost.com/wsexportdata/EnuanFlightsRedirect.aspx";
            var form = $('<form method="post" target="_top" action="{0}"><input type="hidden" name="msg" value="{1}" /><input type="hidden" name="language" value="it" /></form>'.format(url, msg.body));
            $('body').append(form);

            form.submit();
        }
		
        function refreshError(xhr, status, error) {
            // flXHR sometimes raise an ioError (code: 16) exception: "An error occured preventing completion of the request".
            // In this case just resend immediately another /refresh action.
            if (!status && !error && xhr.error == 16)
                setTimeout(refresh, errorSleepTime);

            if (xhr.status == 400) {
                token();
                clearHistory();
                addInfoMsg('Token changed');
            } else {
                //errorSleepTime *= 2;
                setTimeout(refresh, errorSleepTime);
            }
        }
    
        // Comet spinning request.
        function refresh() {
            refreshXhr = Xhr({
                url: config.baseUrl + config.domainMethods + '/refresh',
                policyUrl: config.baseUrl + config.policyPath,
                type: 'POST',
                data: { _xsrf: getXsrf() },
                success: refreshSuccess,
                error: refreshError
            });
        }
    
        // Send a message to MessageCube.
        function receive() {
            var el = $("#{0}-text".format(element.id));
            var msg = el.val();
            el.val('');
            if (msg == '') return;

            Xhr({
                url: config.baseUrl + config.domainMethods + '/receive',
                policyUrl: config.baseUrl + config.policyPath,
                type: 'POST',
                data: { msg: msg, _xsrf: getXsrf() },
                success: function() { },
                error: function() { }
            });

            if (!refreshXhr) {
                errorSleepTime = 500;
                setTimeout(refresh, errorSleepTime);
            }

            return false;
        }

        // Leave the current chat session.
        function leave() {
            Xhr({
                url: config.baseUrl + config.domainMethods + '/leave',
                policyUrl: config.baseUrl + config.policyPath,
                type: 'POST',
                data: { _xsrf: getXsrf() }
            });
        }

        // Render the chat.
        function render() {
			elem.append('<div id="{0}-history" class="livechat-history"><table id="{0}-history-table" width="100%" cellspacing="0" cellpadding="0"></table></div>'.format(element.id));
            elem.append('<textarea id="{0}-text" class="livechat-text" wrap="virtual">Scrivi qui la ricerca del tuo volo, esempio: milano roma andata domani mattina ritorno dopodomani pomeriggio</textarea>'.format(element.id));

            $("#{0}-text".format(element.id)).bind({
                focus: function() {
                    $(this).addClass('livechat-text-focus');
                    $(document).keydown(keyPress);
                },
                blur: function() {
                    $(this).removeClass('livechat-text-focus');
                    $(document).unbind('keydown', keyPress);
                },
				click: function(){
					if($('#ftd').val() == 'true')
					{
						$(this).val('');
						$('#ftd').val('false');
					}					
				}
            }).
            focus();
        };
    
        // Main.
        function main() {
            $(window).unload(function() {
                clearTimeout(refresh);
                leave();
            });
            
            render();
            token(function() {
                refresh();
            });
        };
        
        main();
    };

    $.fn.livechat = function(settings) {
        var config = {
            baseUrl: null,
            policyPath: null,
			domainMethods: null
        };

        if (settings) $.extend(config, settings);
        return this.each(function() {
            return new Livechat(this, config);
        });
    };
})(jQuery);
