function ChatClientUI() {
    
    /**
     * Messages
     */
    
    this.chatPendingMessage = "Searching for an available agent - Please wait";
    this.connectingMessage = "Connecting to chat server - Please wait";
    this.waitingForStaffRes = "Searching for an available agent - Please wait";
    this.navigateAway = "Are you sure you want navigate away?\n Current chat session will be closed.";
    this.connectedMessage = "Connected...";

    /**
     * Initiating listeners array
     */
    this.listeners = new Array ("newMessageListeners", "sessionClosingListeners");
    this.listeners["newMessageListeners"] = new Array();
    this.listeners["sessionClosingListeners"] = new Array();
    this.listeners["UIReady"] = new Array();
    this.listeners["UIDestroyed"] = new Array();

    /**
     * Setting Global Variables
     */

    this.isTyping = false;
    this.frozen = false;
    this.sessionRunning = false;
    this.transientState = false;
    this.peerName = null;
    this.sessionID = null;
    this.lastChatFrom = null;
    this.lastMsgFragmentContainer = null
    /**
     * Predefined chat Tags
     */
    
    //    this.clientPin = $("<img/>")
    //    .attr("src","/chat/images/client-logo.png")
    //    .attr("alt","");
    //    this.staffPin = $("<img/>")
    //    .attr("src","/chat/images/staff-logo.png")
    //    .attr("alt","");
    
    var chatStatusBar;
    var clearBoth = $("<div/>").css("clear","both");
    this.dialog = $('<div/>')
    .attr("class","chat-window");
    this.dialog.append($('<div/>').attr("class","main-chat-window"));
    
    this.messagesContainer =  $('<div/>').attr("class","chat-messages-container");
    this.dialog.find('.main-chat-window').append(this.messagesContainer);
    
    chatStatusBar = $('<div/>').attr("class","chat-status-bar");
    
    //    this.chatBusy = $('<div/>').attr("class","chat-busy");
    //    this.dialog.append(this.chatBusy);
    
    this.peerNameContainer = $('<span/>').attr('class','chat-peer-name');
    this.chatPending = $("<span/>").attr('class','chat-pending-user').text("0");
    
    this.connectingContainer = $('<div/>')
    .attr('class','chat-connecting')
    .append($("<img/>").attr("src","/chat/images/loading.gif").attr("alt","").css("float","left").css("margin-right","3px"))
    .append(this.connectingMessage);
    this.peerStatusContainer = $('<div/>')
    .append(this.peerNameContainer)
    .attr('class','chat-peer-status-bar')
    .append(" is typing...")
    .hide();
    this.connectionTerminatedContainer = $('<div/>')
    .attr('class','chat-connection-terminated')
    .text("Connection Terminated...");
    
    chatStatusBar.append(
        $('<div/>')
        .append(this.connectingContainer)
        .append(this.peerStatusContainer)
        .append(this.connectionTerminatedContainer)
        );
    chatStatusBar.append(clearBoth);    
    this.dialog.append(chatStatusBar);

    this.chatTextBox = $('<textarea/>')
    .attr("cols","50")
    .attr("class","chat-input-textbox")
    .attr("rows","7")
    .attr("diabled","disabled");
    this.sendButton = $("<input/>")
    .attr('class','chat-send-button')
    .attr('type','button')
    .attr('disabled','disabled')
    .attr('value', 'Send');
    
    this.dialog.append(
        $("<div/>")
        .attr("class","chat-box")
        .append(this.chatTextBox)
        );
    this.dialog.append(
        $("<div/>")
        .attr("class","chat-send")
        .append(this.sendButton)
        )
    this.dialog.append(clearBoth);
    
    //<debug>//
    if(ChatEngine.debug == 1){
        var debugTextBox = $("<textarea/>")
        .attr("id","chat-debug-log")
        .css("width","350px")
        .css("height","200px");
        this.dialog.append($("<br/>"));
        this.dialog.append(debugTextBox);
    }
    //</debug>//
    $("body").append(this.dialog);
    
    this.messagesContainer.html("");
    this.peerStatusContainer.hide();
    this.chatTextBox.attr("disabled","disabled");

    /**
     * setting Chat Box Listener
     */

    this.chatTextBox.keypress({
        instance: this 
    }, function(event){
        ChatClientUI.chatBoxListener(event);
    });

    this.sendButton.click({
        instance: this
    }, function (event) {
        ChatClientUI.sendButtonListener(event);
    })
}

/**
 * UI Prototype (setters/getters/trigger functions) &&  (JsEngine Callback Functions)
 */

ChatClientUI.prototype = {
    setNewMessageEventListener: function(listener) {
        this.listeners["newMessageListeners"].push(listener);
    },

    setSessionClosingEventListener: function(listener) {
        this.listeners["sessionClosingListeners"].push(listener);
    },

    setUIReadyEventListener: function(listener){
        this.listeners['UIReady'].push(listener);
    },

    setUIDestroyedEventListener: function(listener) {
        this.listeners['UIDestroyed'].push(listener);
    },

    fireNewMessageEvent: function(event) {
        for(var i=0;i<this.listeners["newMessageListeners"].length;i++)
            this.listeners["newMessageListeners"][i](event);
    },

    fireSessionClosingEvent: function() {
        var event = new Object();
        event.sessionID = this.sessionID;
        event.disableAutoConnect = true;
        for(var i=0;i<this.listeners["sessionClosingListeners"].length;i++)
            this.listeners["sessionClosingListeners"][i](event);
    },

    fireUIReadyEvent: function(event) {
        for(var i=0;i<this.listeners["UIReady"].length;i++)
            this.listeners["UIReady"][i](event);
    },

    fireUIDestroyedEvent: function(event) {
        for(var i=0;i<this.listeners["UIReady"].length;i++)
            this.listeners["UIDestroyed"][i](event);
    },

    initiateUIElements: function(UIElements){
        if(UIElements != null){

            this.dialog.attr("title",UIElements.dialogTitle);
            this.dialog.dialog({
                resizable: true,
                autoOpen: false,
                width: 388,
                minWidth:388,
                height: 343,
                maxHeight: 343,
                minHeight: 343
            });
            this.dialog.bind("dialogbeforeclose", {
                instance: this
            } ,function(event, ui){
                if(event.data.instance.isSessionRunning()){
                    if(!event.data.instance.isFrozen()){
                        event.data.instance.freeze();
                        event.data.instance.fireSessionClosingEvent();
                    }
                    return false;
                }
            });

            this.dialog.bind("dialogclose", {
                instance: this
            }, function(event, ui){
                event.data.instance.reset();
                event.data.instance.fireUIDestroyedEvent(null);
            });
        }
    },

    isSessionRunning: function(){
        return this.sessionRunning;
    },

    isFrozen: function(){
        return this.frozen;
    },

    openChatDialog: function(){
        this.dialog.dialog("open");
        this.fireUIReadyEvent(null);
    },

    freeze: function(){
        this.frozen = true;
        $(this.dialog.dialog("widget")).css("cursor", "wait");
        $(this.chatTextBox).attr("disabled", "disabled");
        $(this.sendButton).attr("disabled", "disabled");
    },
    
    //Will simply change the message till we hear something from the staff members side
    addSession: function(sessionID, peerName) {
        this.peerName = peerName;
        this.sessionID = sessionID;
        this.peerNameContainer.text(peerName);
        this.messagesContainer.text("");
        this.transientState = true;
        this.connectingContainer
        .html("")
        .append($("<img/>").attr("src","/chat/images/loading.gif").attr("alt","").css("float","left").css("margin-right","3px"))
        .append(this.waitingForStaffRes);
        this.sessionRunning = true;
        $(window).bind('beforeunload', (function(that){
            return function(){
                return that.navigateAway;
            }
        }(this)));
    },
    
    initSession: function(sessionID) {
        this.chatTextBox
        .removeAttr("disabled")
        .focus();
        this.sendButton.removeAttr("disabled");
        this.connectingContainer.text(this.connectedMessage);
        setTimeout((function(that){
            return function(){
                that.connectingContainer.fadeOut(900);
            }
        }(this)),900);
        this.transientState = false;
        this.sessionRunning = true;
    },

    closeSession: function(sessionID) {
        this.sessionRunning = false;
        this.connectingContainer
        .html("")
        .append($("<img/>").attr("src","/chat/images/loading.gif").attr("alt","").css("float","left").css("margin-right","3px"))
        .append(this.connectingMessage).hide();
        $(window).unbind('beforeunload');
        if(this.frozen)
            this.dialog.dialog("close");
        else{
            this.chatTextBox.attr("disabled","disabled");
            this.sendButton.attr("disabled", "disabled");
            this.connectionTerminatedContainer.show();
            this.peerStatusContainer.hide();
        }
    },

    setPeerTypingStatus: function(sessionID, status) {
        if(status && this.transientState){
            this.initSession(sessionID)
        } else if (status) {
            this.peerStatusContainer.show();
        } else {
            this.peerStatusContainer.hide();
        }
    },

    getLocalTypingStatus: function() {
        if(this.chatTextBox.val() == "")
            this.isTyping = false;
        else 
            this.isTyping = true;
        return this.isTyping;
    },
    
    setMessage: function(sessionID, text) {
        if(this.transientState){
            this.initSession(sessionID)
        }
        var urlMatched = this.isUrl(text);
        text = $("<div/>").text(text).html();
        if(urlMatched != null){
            text = text.replace(urlMatched[0],'<a target="_blank" href="'+urlMatched[0]+'">'
                +urlMatched[0]+'</a>');
        }
        this.appendToMessageContainer(this.peerName+": ", this.detectSmile(text), ChatClientUI.STAFF);
        this.messagesContainer.scrollTop(this.messagesContainer.prop("scrollHeight"));
    },

    newMessage: function() {
        var event = new Object();
        event.sessionID = this.sessionID;
        event.text = this.chatTextBox.val();
        var urlMatched = this.isUrl(event.text);
        var printableText = $("<div/>").text(this.chatTextBox.val()).html();
        if(urlMatched != null){
            printableText = printableText.replace(urlMatched[0],'<a target="_blank" href="'+urlMatched[0]+'">'
                +urlMatched[0]
                +'</a>');
        }
        if(event.text != ""){
            this.fireNewMessageEvent(event);
            this.appendToMessageContainer("You: ", this.detectSmile(printableText), ChatClientUI.CLIENT);
            this.chatTextBox.val("");
            this.messagesContainer.scrollTop(this.messagesContainer.prop("scrollHeight"));
        }
    },
    
    appendToMessageContainer: function(label,text,peer){
        if(peer == this.lastChatFrom){
            this.lastMsgFragmentContainer.find(".message-text-container").append("<br/>"+text);
        } else {
            this.lastMsgFragmentContainer = $("<div/>").css("margin-bottom","4px")
            .append(
                $("<div/>").addClass("message-text-container")
                .append($("<span/>").css("font-weight","bold").text(label))
                .append(text))
            .addClass("chat-peer-message");
            if(peer == ChatClientUI.CLIENT){
                this.lastMsgFragmentContainer.addClass("chat-client-message");
            } else {
                this.lastMsgFragmentContainer.addClass("chat-staff-message");
            }
            this.messagesContainer.append(this.lastMsgFragmentContainer);
        }
        this.lastChatFrom = peer;
    },
    
    detectSmile: function(text){
        text = text
        .replace(/(\s|^):\)(\s|$)/,'<span class="smile">:)</span>')
        .replace(/(\s|^):\((\s|$)/,'<span class="smile">:(</span>')
        .replace(/(\s|^):D(\s|$)/i,'<span class="smile">:D</span>')
        .replace(/(\s|^):P(\s|$)/i,'<span class="smile">:P</span>')
        .replace(/(\s|^):S(\s|$)/i,'<span class="smile">:S</span>')
        .replace(/(\s|^):@(\s|$)/,'<span class="smile">:@</span>')
        .replace(/(\s|^):\|(\s|$)/,'<span class="smile">:|</span>');
        return text;
    },
    
    setPendingUsers : function(pending){
        if(pending > 0){
            this.chatPending.text(pending);
            this.connectingContainer.html("")
            //.append(this.chatPending)
            //.append(" Users pending. Please wait, our representative will be with you shortly");
            .append($("<img/>").attr("src","/chat/images/loading.gif").attr("alt","").css("float","left").css("margin-right","3px"))
            .append(this.chatPendingMessage);
        }
    },

    reset: function() {
        //this.chatBusy.hide();
        this.messagesContainer.text("");
        this.chatTextBox.attr("disabled","disabled");       
        this.sendButton.attr("disabled", "disabled");
        $(this.dialog.dialog("widget")).css("cursor", "auto");
        this.connectingContainer.show();
        this.connectionTerminatedContainer.hide();
        this.peerName = null;
        this.peerNameContainer.text("");
        this.peerStatusContainer.hide();
        this.sessionID = null;
        this.sessionRunning = false;
        this.frozen = false;
        this.lastChatFrom = null;
        this.lastMsgFragmentContainer = null
    },

    isUrl: function(text) {
        return text.match(/(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/);
    },
    ringTheBell : function() {
        this.ding.StopPlay();
        this.ding.Play();
    }
}

ChatClientUI.STAFF = 0;
ChatClientUI.CLIENT = 1;

ChatClientUI.chatBoxListener = function(event){
    var UIInst = event.data.instance;
    var keynum = event.keyCode;

    if(keynum == 13){
        UIInst.newMessage();
        event.preventDefault();
    } else {
        UIInst.isTyping = true;
    }
}

ChatClientUI.sendButtonListener = function(event) {
    event.data.instance.newMessage();
}
