let Chat = function () {
    "use strict";

    let resize_timer;

    // chats abiertos
    let me_chat = []; // Array which stores the chatboxes
    let me_chat_event = []; // Array which stores the events of chatboxes


    // configuracion de los chat
    let me_chat_settings = {};
    me_chat_settings.box_update_timer = 3000; // Time in milliseconds to update chatboxes
    me_chat_settings.box_hidden = true; // Hide chatbox when click on its header
    me_chat_settings.path = '/chat/'; // Folder path with meChat files

    /*
     # ATTRIBUTES
     */
    me_chat_settings.box_allow_mobile = true; // Allow mobile mode to chatbox
    me_chat_settings.box_header_status = true; // Update status (online, offline ...)
    me_chat_settings.box_allow_emojis = true; // Allow use of emojis
    me_chat_settings.box_allow_imageupload = true; // Allow uploading pictures
    me_chat_settings.box_allow_imageupload_maxsize = 1.5; // Maximum image size, in megabytes (Important: 0 = unlimited)

    /*
     # STYLE
     */
    me_chat_settings.box_color = '#4080ff'; // Color of chatbox
    me_chat_settings.box_color_received_background = '#f1f0f0'; // Background color of chatbox, message received
    me_chat_settings.box_color_sent_background = '#4080ff'; // Background color of chatbox, message sent
    me_chat_settings.box_color_received_text = '#4b4f56'; // Color of message received
    me_chat_settings.box_color_sent_text = 'white'; // Color of message sent

    /*
     # SIZE, SPACE, AND BODY
     */
    me_chat_settings.box_width = 235; // Width of chatbox, change also in the style sheet
    me_chat_settings.box_spacebetween = 5; // Space between chatboxes
    me_chat_settings.box_betweencorner = 0; // Space to the right of the screen
    me_chat_settings.box_scrolllock = true; // Disable the scroll (HTML, body) while giving scroll in the chatbox

    /*
     # ALERTS
     */
    me_chat_settings.box_alert_messagereceived = true; // Enable receive messages alerts, when receive messages

    /*
     # FLASH NOTIFICATION
     */
    me_chat_settings.box_alert_header_flash = true; // Enable flash of chatboxes, if receive messages
    me_chat_settings.box_alert_header_flash_color = '#0D47A1'; // Flash color, or second header color

    /*
     # SOUND NOTIFICATION
     */
    me_chat_settings.box_alert_sound = true; // Enable alert sounds
    me_chat_settings.box_alert_sound_file = 'chat.ogg'; // Type of alert sound (Available: 1.mp3, 2.mp3, 3.mp3, 4.mp3)

    /*
     # MESSAGES
     */
    me_chat_settings.box_message_timeseparator = true; // Enable time separator
    me_chat_settings.box_message_popoverdate = true; // Enable message popover (event: mouseover)
    me_chat_settings.box_message_date = true; // Enable date of the message (event: tap) (mobile)
    me_chat_settings.box_message_seen = true; // Enable seen date of the sent message (mobile - event: tap) and (desktop - last message)
    me_chat_settings.box_message_userpicture = true; // Show user image
    me_chat_settings.box_contenteditable = true; // Use attr "contenteditable" instead of <textarea> (This allows: Transform unicode characters in images)
    me_chat_settings.box_contenteditable_elastic = true; // Enable auto resize of the contenteditable based on content

    // Strings of meChat
    let me_chat_strings = {};

    /*
     # GENERAL
     */
    me_chat_strings.menubox_title = 'Mensajes'; // Title of chatboxes menu
    me_chat_strings.box_button_loadoldmessages = 'Load old messages'; // Button to load old messages
    me_chat_strings.box_properties_lastmessage_img_initials = '(image)'; // Transform image tag for the property (last received message) of the chatbox
    me_chat_strings.box_properties_lastmessage_yt_initials = '(video)'; // Transform youtube iframe tag for the property (last received message) of the chatbox
    me_chat_strings.box_textarea = 'Escriba un mensaje...'; // Placeholder textarea of the chatbox

    me_chat_strings.box_message_popoverdate = 'G:ia'; // Format the date of the message popover
    me_chat_strings.box_message_date = 'G:ia'; // Format the date of message
    me_chat_strings.box_message_seen = '\\Seen'; // Format the seen date of the message
    me_chat_strings.box_lastmessage_seen = '\\Seen g:i A'; // Format the seen date of the last message

    /*
     # ALERTS
     */
    me_chat_strings.box_alert_received = 'Message received!'; // Received message, alert text
    me_chat_strings.box_alert_loadingoldmessages = 'Loading...'; // Loading old messages, alert text

    /*
     # ERRORS
     */
    me_chat_strings.box_error_sendmessage = 'This message didn\'t send. Check your internet connection and try again.'; // Connection problem
    me_chat_strings.box_error_imageupload_maxsize = 'Maximum image size has been exceeded.'; // If the maximum image size is exceeded


    /*
     # TIME SEPARATOR
     */
    me_chat_strings.box_message_timeseparator_today = 'g:i A'; // Today
    me_chat_strings.box_message_timeseparator_anotherday = 'm/d/Y - g:i A'; // Another day
    me_chat_strings.box_message_timeseparator_anotheryear = 'm/d/Y - g:i A'; // Another year


    // Using attr "contenteditable" instead of <textarea>
    let me_chat_contenteditable = false;
    if ("contentEditable" in document.documentElement && me_chat_settings.box_contenteditable) {
        me_chat_contenteditable = true;
    }

    // meChat settings for the user
    let me_chat_usersettings = {};
    me_chat_usersettings.disable_notifications = false; // Disable notifications from chatboxes (flash)
    me_chat_usersettings.disable_sounds = false; // Disable sounds of chatboxes

    let time = function() {
        return Math.floor(new Date().getTime() / 1000);
    }

    let countDisplayed = function () {
        let count = 0;
        let chat;
        let keys = Object.keys(me_chat);
        for (let i=0, len=keys.length; i<len; i++) {
            chat = me_chat[keys[i]];
            if (chat.isDisplayed()) {
                count++;
            }
        }

        return count;
    }

    let dateFormat = function (format, timestamp) {
        let date = new Date(timestamp * 1000); // Date Object
        let hours24 = date.getHours(); // 24 hours
        let hours12 = date.getHours(); // 12 hours
        if (hours12 > 12) {
            hours12 -= 12;
        }
        else if (hours12 === 0) {
            hours12 = 12;
        }
        let minute = date.getMinutes();
        let second = date.getSeconds();
        let year = date.getFullYear();
        let month = date.getMonth() + 1;
        let day = date.getDate();

        // Converted
        let converted = {};

        // Hours - with leading zeros - 01,12
        converted.g = (hours12 >= 1 && hours12 <= 9) ? ('0' + hours12) : hours12;
        format = meChat_replaceUnescaped(format, 'g', converted.g);
        // without leading zeros - 1, 12
        converted.G = hours12;
        format = meChat_replaceUnescaped(format, 'G', converted.G);


        // Hours - with leading zeros - 00,23
        converted.h = (hours24 >= 0 && hours24 <= 9) ? ('0' + hours24) : hours24;
        format = meChat_replaceUnescaped(format, 'h', converted.h);
        // without leading zeros - 0,23
        converted.H = hours24;
        format = meChat_replaceUnescaped(format, 'H', converted.H);


        // Minutes - with leading zeros - 00,59
        converted.i = (minute >= 0 && minute <= 9) ? ('0' + minute) : minute;
        format = meChat_replaceUnescaped(format, 'i', converted.i);
        // without leading zeros - 0,59
        converted.I = minute;
        format = meChat_replaceUnescaped(format, 'I', converted.I);


        // Seconds - with leading zeros - 00,59
        converted.s = (second >= 0 && second <= 9) ? ('0' + second) : second;
        format = meChat_replaceUnescaped(format, 's', converted.s);
        // without leading zeros - 0,59
        converted.S = second;
        format = meChat_replaceUnescaped(format, 'S', converted.S);


        // Year - Full Year - 2016
        converted.y = year;
        format = meChat_replaceUnescaped(format, 'y', year);
        // last two numbers - 16
        format = meChat_replaceUnescaped(format, 'Y', year % 100);


        // Month - with leading zeros - 01,12
        converted.m = (month >= 0 && month <= 9) ? ('0' + month) : month;
        format = meChat_replaceUnescaped(format, 'm', converted.m);
        // without leading zeros - 1,12
        converted.M = month;
        format = meChat_replaceUnescaped(format, 'M', converted.M);


        // Day - with leading zeros - 01,31
        converted.d = (day >= 0 && day <= 9) ? '0'+day : day;
        format = meChat_replaceUnescaped(format, 'd', converted.d);
        // without leading zeros - 1,31
        converted.D = day;
        format = meChat_replaceUnescaped(format, 'D', converted.D);


        // Ante meridiem & Post meridiem - lowercase (am,pm)
        converted.a = hours24 >= 12 ? 'pm' : 'am';
        format = meChat_replaceUnescaped(format, 'a', converted.a);
        // uppercase (AM,PM)
        converted.A = converted.a.toUpperCase();
        format = meChat_replaceUnescaped(format, 'A', converted.A);

        return format;
    }

    function meChat_replaceUnescaped(string, searchvalue, newvalue) { //console.log("meChat_replaceUnescaped():"+string)
        let indexes = allIndexOfString(string, searchvalue); // Total de encontrados
        let totalReplaced = 0; // Total de substituídos
        let lastReplace = 0; // Último encontrado

        while (totalReplaced <= indexes.length - 1) // Total de encontrados (- 1)
        {
            let st_instance = string.indexOf(searchvalue, lastReplace); // Primeiro encontrado, depois do último encontrado
            lastReplace = st_instance + 1; // Último encontrado

            if (string[st_instance - 1] != '\\') // Não foi escapado
            {
                let begin = string.substr(0, st_instance); // Começo
                let end = string.substr(begin.length + searchvalue.length); // Fim
                string = begin + newvalue + end; // Começo + newvalue + Fim
            }
            else // Escapado
            {
                let begin = string.substr(0, st_instance - 1); // Começo
                let end = string.substr(begin.length + 1); // Fim
                string = begin + end; // Começo + Fim
            }
            totalReplaced++; // Contar voltas (total de substituídos ou Ñ)
        }
        return string; // Retornar string
    }

    function allIndexOfString(string, searchvalue) {
        let indexes = [];

        for (let pos = string.indexOf(searchvalue); pos !== -1; pos = string.indexOf(searchvalue, pos + 1)) {
            indexes.push(pos);
        }
        return indexes;
    }

    let initListeners = function () {

        // eventos que ocurren en el tab
        $(document).on('click touchstart mouseenter', '.me-chat-box-manager-tabs > a', function (event) {
            let tabID = $(this).data('me-chat-tab_target');

            if (event.type == 'click' || event.type == 'touchstart') {
                vChat.showTab(tabID);
            }
        });

        // Sent & seen date of the message (event: tap)
        let messageTap = 0;
        $(document).on('touchstart', '.me-chat-box-message-sent, .me-chat-box-message-received', function () {
            messageTap = new Date().getTime();
        });
        $(document).on('touchend', '.me-chat-box-message-sent, .me-chat-box-message-received', function () {
            if ((new Date().getTime() - messageTap) > 150) return;

            let messageDOM_date = $(this).closest('.me-chat-box-body-content-message').find('.me-chat-box-message-received-date, .me-chat-box-message-sent-date, .me-chat-box-message-sent-seen');

            $(messageDOM_date).not($('.me-chat-box-message-received-date.expand, .me-chat-box-message-sent-date.expand, .me-chat-box-message-sent-seen.expand').removeClass('expand')).toggleClass('expand');
        });

// Popover sent & received date (event: mouseenter, mouseleave)
        let popover_Temp = false; // Save popover temporarily
        $(document).on('mouseenter', '.me-chat-box-message-sent, .me-chat-box-message-received', function (event) {
            let messageDOM_popover = $(this).parent().find('.me-chat-box-message-popover');

            // Stop if the message has height greater than 80px
            if (parseInt($(this).css('height')) > 80) return;

            // Get the position of the element on the screen
            let messageDOM_position = $(this).offset();
            messageDOM_position.y = messageDOM_position.top - $(window).scrollTop();
            messageDOM_position.x = messageDOM_position.left - $(window).scrollLeft();

            // Get half Y of the element
            messageDOM_position.y += (parseFloat($(this).css('height')) / 2) - (parseFloat($(messageDOM_popover).css('height')) / 2);

            if (event.target.className == 'me-chat-box-message-sent') {
                // Get caret width
                let messageDOM_popover_caret = parseFloat($(messageDOM_popover).find('.me-chat-box-message-popover-caretleft, .me-chat-box-message-popover-caretright').css('border-left-width'));
                messageDOM_popover_caret += parseFloat($(messageDOM_popover).find('.me-chat-box-message-popover-caretleft, .me-chat-box-message-popover-caretright').css('border-right-width'));

                // Get end X of the element
                messageDOM_position.x += parseFloat($(this).css('width')) + (messageDOM_popover_caret * 2.2);

                $(messageDOM_popover).css('left', messageDOM_position.x + 'px'); // Set X position
                $(messageDOM_popover).css('top', messageDOM_position.y + 'px'); // Set Y position
            }
            else {
                // Get caret width
                let messageDOM_popover_caret = parseFloat($(messageDOM_popover).find('.me-chat-box-message-popover-caretleft, .me-chat-box-message-popover-caretright').css('border-left-width'));
                messageDOM_popover_caret += parseFloat($(messageDOM_popover).find('.me-chat-box-message-popover-caretleft, .me-chat-box-message-popover-caretright').css('border-right-width'));

                messageDOM_position.x = ($(window).width() - messageDOM_position.x) + (messageDOM_popover_caret * 2.2);

                $(messageDOM_popover).css('right', messageDOM_position.x + 'px'); // Set X position
                $(messageDOM_popover).css('top', messageDOM_position.y + 'px'); // Set Y position
            }

            popover_Temp = $(messageDOM_popover).clone().appendTo('body');
            $(popover_Temp).show(); // Show Popover
        });
        $(document).on('mouseleave', '.me-chat-box-message-sent, .me-chat-box-message-received', function (event) {
            $(popover_Temp).remove(); // Remove Popover
        });


        //fm click dentro del chatbox
        $(document).on("click touchstart", ".me-chat-box-body-content, .me-chat-box-body-submit input", function (event) {
            let chatDOM = $(this).closest('.me-chat-box');
            let chatID = $(chatDOM).data('me-chat-id');

            let chat = getChat(chatID);
            chat.clickInside();
        });

        // al escribir en el input
        let is_typing = false;
        $(document).on("keyup", ".me-chat-box-body-submit input", function (event) {
            let message = $(this).val();

            let chatDOM = $(this).closest('.me-chat-box');
            let chatID = $(chatDOM).data('me-chat-id');
            let chat = getChat(chatID);

            if (event.keyCode == 13 && message.trim().length != 0) {
                chat.send(message);
                $(this).val('');
            }
            else {
                if (!is_typing) {
                    is_typing = true;
                    chat.sendTyping();
                    setTimeout(function() {
                        is_typing = false;
                    }, 3000);
                }
            }
        });

        $(document).on("focusin", ".me-chat-box-body-submit .me-chat-box-body-submit-contenteditable", function (event) {
            $(this).parent().find('.me-chat-box-body-submit-contenteditable-placeholder').hide();
        });


        //fm click to close the chatbox
        $(document).on("click touchstart", ".me-chat-box-header-close", function () {
            let chatID = $(this).closest('.me-chat-box').data('me-chat-id');
            meChat_Close(chatID);
        });

        //fm click en el header del chatbox
        $(document).on("click", ".me-chat-box-header", function (event) {
            event.stopImmediatePropagation();

            let chatID = $(this).closest('.me-chat-box').data('me-chat-id');
            let chat = getChat(chatID);
            if (chat) {
                chat.toogleShow();
            }
        });

        //fm click en los items
        $(document).on("click", ".me-chat-item-message", function (event) {
            let chatID = $(this).data('id');
            let chatType = $(this).data('type');
            openChat(chatID, chatType);
        });
    }

    //---

    // checa si el espacio en pantalla es INSUFICIENTE para agregar un nuevo chatbox
    function meChat_lackspace(for_remove) {

        // calculamos total de espacio ocupado por los chatboxes que estan visibles
        let right_after;
        if (for_remove === true) {
            right_after = ((me_chat_settings.box_spacebetween + me_chat_settings.box_width) * countDisplayed()) + me_chat_settings.box_betweencorner;
        }
        else {
            right_after = ((me_chat_settings.box_spacebetween + me_chat_settings.box_width) * (countDisplayed() + 1)) + me_chat_settings.box_betweencorner;
        }

        // devuelve TRUE si no hay espacio suficiente
        if (right_after >= window.innerWidth) {
            return true;
        }

        return false;
    }

    let onResizeWindows = function () {
        let chat;

        // checamos para agregar chatbox
        if (!meChat_lackspace()) {
            chat = recentChatNotDisplayed();
            if (chat) {
                chat.displayedOn();
                reOrder();
            }
        }

        // checamos para quitar chatbox
        else if (meChat_lackspace(true)) {
            chat = oldestChatOpened();
            if (chat) {
                chat.displayedOff();
                reOrder();
            }
        }
    }

    // ultimom chat abierto y VISIBLE
    let oldestChatOpened = function () {
        reSort();

        let keys = Object.keys(me_chat); console.log(keys);
        let chat;
        for (let i=1, len=keys.length; i<len; i++) {
            chat = me_chat[keys[i]];

            if (chat.isDisplayed()) {
                return chat;
            }
        }
    }

    let recentChatNotDisplayed = function () {
        reSort();

        let keys = Object.keys(me_chat);
        let chat;
        for (let i=keys.length-1; i>=0; i--) {
            chat = me_chat[keys[i]];

            if (!chat.isDisplayed()) {
                return chat;
            }
        }
    }

    let reSort = function () {
        me_chat.sort(function(a, b){
            if(a.created_at < b.created_at) return -1;
            if(a.created_at > b.created_at) return 1;
            return 0;
        });
    }

    function reOrder() { //console.log("reOrder()")
        reSort();

        let keys = Object.keys(me_chat); console.log(keys);

        let chat;
        let meChat_orderred = 0;
        let me_chat_right = 0;
        for (let i=0, len=keys.length; i<len; i++) {
            chat = getChat(keys[i]);

            if (chat.isDisplayed()) {
                me_chat_right = (((me_chat_settings.box_spacebetween + me_chat_settings.box_width) * meChat_orderred) + me_chat_settings.box_betweencorner);
                chat.html.css('left', me_chat_right + 'px');
                meChat_orderred++;
            }
        }
    }

    // crea la ventana principal del chat (agrega en ella los tabs que ya fueron creados)
    let openChatMain = function () { console.warn("chat.openChatMain()")

        let chat = new ChatBox(0);
        me_chat.push(chat);

        let me_chat_string = '' +
            '<div class="me-chat-box me-chat-box-menu" style="left: ' + me_chat_settings.box_betweencorner + 'px;" data-me-chat-id="0">' +
            '   <div class="me-chat-box-header" style="background-color: ' + me_chat_settings.box_color + ';">' +
            '      <div class="me-chat-box-header-name">' + me_chat_strings.menubox_title + '</div>' +
            '      <div class="me-chat-box-header-close">&minus;</div>' +
            '   </div>' +
            '   <div class="me-chat-box-manager">' +
            '       <div class="me-chat-box-manager-content" style="display: block;"><ul></ul></div>' +
            '   </div>' +
            '</div>';

        $('body').append(me_chat_string);

        chat.html = $("div[data-me-chat-id='0']");

        // por defecto aparece minimizado
        chat.toogleShow();
    }

    // abre un chatbox
    let openChat = function (id, mini) { console.warn('Chat.openChat() id:' + id + ' mini:'+mini);

        // hay que checar si el item existe, ya que los chats pueden abrirse de coockies(en el caso de soporte y supadmin)
        let item = vChat.getItem(id); //console.log(item);
        if (!item) { return; }

        // checa is el chatbox ya esta abierto
        let chat = getChat(id);

        // si el chat existe y esta visible, no se hace nada
        if (chat !== null && chat.isDisplayed()) {
            console.log(chat);
            console.log("existe y esta visible");

            if (chat.isHidden()) {
                chat.toogleShow();
            }
            return;
        }

        // si el chat existe y esta oculto
        if (chat !== null) {
            //console.log("existe y esta oculto");

            // checa si hay espacio para agregar el nuevo chatbox, si no hay espacio, se elimina el chatbox mas viejo
            if (meChat_lackspace()) {
                let chatOld = oldestChatOpened();
                chatOld.displayedOff();
                chat.displayedOn();
            }

            chat.displayedOn();
            reOrder();
            return;
        }

        // checa el espacio disponible para mostrar el chatbox
        if (meChat_lackspace()) {
            let chatOld = oldestChatOpened();
            chatOld.displayedOff();
            reOrder();
        }

        // Determine space that the new chat box must have right corner
        let me_chat_right = (((me_chat_settings.box_spacebetween + me_chat_settings.box_width) * countDisplayed()) + me_chat_settings.box_betweencorner); //console.log("me_chat_right:"+me_chat_right)

        let messages = Messages.getMessages(id); console.log(messages);

        chat = new ChatBox(item);
        me_chat[id] = chat;

        let me_chat_string = '' +
            '<div class="me-chat-box" style="left: ' + me_chat_right + 'px;" data-me-chat-id="' + id + '">' +
            '<div class="me-chat-box-header" style="background-color: ' + me_chat_settings.box_color + '">' +
            '<div class="me-chat-box-header-status">&#9679;</div>' +
            '<div class="me-chat-box-header-name">' + item.name + '</div>' +
            '<div class="me-chat-box-header-close">&times;</div>' +
            '<div class="me-chat-box-header-clear" style="line-height: 25px;"><i class="fa fa-trash" aria-hidden="true"></i></div>' +

            '</div>' +
            '<div class="me-chat-box-body">' +
            '<div class="me-chat-box-body-alert" style="background-color: ' + me_chat_settings.box_color + '"></div>' +
            '<div class="me-chat-box-body-content" style="display: block;">' +
            '<div class="me-chat-box-body-content-message"></div>' +
            '</div>' +
            '<div class="me-chat-box-body-submit">' +
            '<input maxlength="200" placeholder="' + me_chat_strings.box_textarea + '" />' +
            '<div class="me-chat-box-body-submit-icon"></div>' +
            '</div>' +
            '</div>' +
            '</div>';
        $('body').append(me_chat_string);

        chat.html = $("div[data-me-chat-id='" + id + "']");
        item.evalEstatus();

        // se imprimen los mensajes
        messages.forEach(function (row, index) {
            let msg = Messages.compose(row);

            if (index == 0)  {
                item.firstmessage = msg;
            }

            chat.drawMessage(msg);

            // checamos mensajessin leer
            if (msg.isNotSelf() && !msg.isRead()) {
                item.unread += 1;
            }
        });

        chat.scrollToBottom();
        chat.evalUnread();

        // si va minimizada
        if (mini === true) {
            chat.toogleShow();
        }

        reOrder();

        // solicitamos los mensajes
        requestMessagesFromServer(id);
    }

    let getChat = function(id) { //console.log("getChat():" + id); console.log(me_chat[id]);
        if (me_chat[id]) {
            return me_chat[id];
        }

        return null;
    }

    let removeChat = function(id) {
        delete me_chat[id];
        return true;
    }

    //fm close chatbox
    let meChat_Close = function (chatID) { console.log("meChat_Close(): " + chatID);
        // evitar cerrar el chatroom
        if (!chatID) { return; }

        let chat = getChat(chatID);
        if (chat) {
            chat.close();
        }

        removeChat(chatID);
        reOrder();
    }

    // Add event to chatbox
    function meChat_Event(event_, function_) {
        let me_chat_obj = {};
        me_chat_obj.action = event_;
        me_chat_obj.function = function_;
        me_chat_event.push(me_chat_obj);
    }

    //fm buscamos chats
    let start = function (usuarios) { console.warn("Chat.start()");

        // creamos la lista de usuarios en el chatbox general
        usuarios.forEach(function (u) {
            vChat.addTabItem(new ChatItem(u));

            // si el chat tiene mensajes sin leer, lo abrimos
            if (parseInt(u.unread) > 0) {
                openChat(u.id);
            }
        });

        // muestra el tab que contiene la lista de usuarios
        vChat.showTab(0);
    }

    // solicitamos al servidor pack de mensajes de un usuario
    let requestMessagesFromServer = function(chat_id) { console.warn("Chat.requestMessagesFromServer(): " + chat_id);
        let last_message_id = Messages.getLastMessageId(chat_id);

        Server.send({
            'action': packet.CHAT_REQUEST_LAST_MESSAGES,
            'user_id': chat_id,
            'last_message_id': last_message_id,
        });
    }

    let onRecvMessagePack = function (data) { console.warn("Chat.onRecvMessagePack()"); console.log(data);
        let friend_id = data.user_id;
        let messages = data.messages;

        messages.forEach(function (message) {
            if (!Messages.exists(message.id)) {
                let msg = Messages.composeRaw(message);
                Messages.add(msg);
            }
        });

        // notificamos de que hemos recibido los mensajes
        Messages.setDelivered(friend_id);
        Server.sendChatDelivered(friend_id);
    }

    return {
        init: function () {
            clearTimeout(resize_timer);
            window.onresize = function() {
                clearTimeout(resize_timer);
                resize_timer = setTimeout(function() {
                    Chat.onResizeWindows();
                }, 100);
            };

            initListeners();
            vChat.addTab('Usuarios');
            openChatMain();
            vChat.showTab(0);
        },

        close: function () {
            $('.me-chat-box').remove();
        },

        start: start,
        onRecvMessagePack: onRecvMessagePack,
        getChats: function () {
            return me_chat;
        },

        countChats: function() {
            return (Object.keys(me_chat).length - 1);
        },

        time: time,

        path: function () {
            return me_chat_settings.path;
        },

        soundFile: function () {
            return me_chat_settings.box_alert_sound_file;
        },

        onResizeWindows: onResizeWindows,
        openChat: openChat,
        getChat: getChat,

        recv: function (data) { console.log("Chat.recv()"); console.log(data);
            let msg = Messages.composeRaw(data);
            if (!msg.isValid()) {
                return;
            }

            Messages.add(msg);

            let box = null;

            if  (msg.isSelf()) { console.log("AUTOR SENDER")
                box = getChat(data.receiver); //console.log(box);
            }
            else { console.log("AUTHOR RECEIVER")
                box = getChat(data.sender); //console.log(box);
            }

            // si la ventana de chat esta cerrada
            if (!box) {
                // en este caso  no es necesario llamar 'box.recv()',
                // ya qu todos los mensajes seran agregados en el openChat()
                let item = vChat.getItem(data.sender);
                openChat(item.id, item.type);
            }
            else {
                box.recv(msg);
            }
        },

        box_color: function () {
            return me_chat_settings.box_color;
        },

        box_color_received_background: function () {
            return me_chat_settings.box_color_received_background;
        },

        box_color_received_text: function () {
            return me_chat_settings.box_color_received_text;
        },

        box_color_sent_text: function () {
            return me_chat_settings.box_color_sent_text;
        },

        box_alert_header_flash_color: function () {
            return me_chat_settings.box_alert_header_flash_color;
        },

        box_color_sent_background: function () {
            return me_chat_settings.box_color_sent_background;
        },

        msgHtml: function(message, type) {
            if (type == Co.MSG_TYPE_AUDIO) {
                return '<audio controls><source src="'+ message.getAudio()+'" type="audio/ogg"></audio>';
            }

            if (type == Co.MSG_TYPE_IMAGE) {
                return '<div class="me-chat-box-message-image" data-me-chat-href="' + message.getImage() + '" style="background-image: url(' + message.getImage() + ')">';
            }

            let returnMessage = message.replace(/&/g, '&amp;'); // character &
            returnMessage = returnMessage.replace(/</g, '&lt;'); // character <
            returnMessage = returnMessage.replace(/>/g, '&gt;'); // character >
            returnMessage = returnMessage.replace(/"/g, '&quot;'); // character "
            returnMessage = returnMessage.replace(/'/g, '&#39;'); // character '
            return returnMessage;
        },
        dateFormat: dateFormat,

        meChat_Event: meChat_Event,

        setLeido: function (data) {
            let chat = getChat(data.receiver);
            chat.setLeido();
        },

        setRecibido: function (data) {
            let chat = getChat(data.receiver);
            chat.setRecibido();
        }
    }
}();