{% extends "base.html" %}
{% block title_row %}{% endblock %}
{% block title_ruler %}{% endblock %}
{% block title %} {{_('Chat Box')}} {% endblock %}
{% block js_media %}

<script type="text/javascript" src="{{ static('mathjax_config.js') }}"></script>
<script type="text/javascript" src="{{ static('event.js') }}"></script>
<script src="https://unpkg.com/@popperjs/core@2"></script>
<script type="module" src="https://unpkg.com/emoji-picker-element@1"></script>
<script type="text/javascript">
let message_template = `
{% with message=message_template %}
    {% include "chat/message.html" %}
{% endwith %}  
`;
let META_HEADER = [
    "{{_('Recent')}}",
    "{{_('Following')}}",
    "{{_('Admin')}}",
    "{{_('Other')}}",
];
</script>
<script type="text/javascript">
    window.currentPage = 1;
    window.limit_time = 24;
    window.messages_per_page = 50;
    window.room_id = "{{room if room else ''}}";
    window.unread_message = 0;
    window.other_user_id = "{{other_user.id if other_user else ''}}";
    window.num_pages = {{paginator.num_pages}};
    window.lock = false;
    window.lock_click_space = false;
    window.pushed_messages = new Set();
    let isMobile = window.matchMedia("only screen and (max-width: 799px)").matches;

    function load_page(page, refresh_html=false) {
        var param = {
            'page': page,
        }
        $.get("{{ url('chat', '') }}" + window.room_id, param)
            .fail(function() {
                console.log("Fail to load page " + page);
            })
            .done(function(data) {
                if (refresh_html) {
                    $('#chat-log').html('');
                    $('#chat-box').scrollTop($('#chat-box')[0].scrollHeight);
                    window.lock = true;
                }

                window.num_pages = parseInt($('<div>' + data + '</div>').find('#num_pages').html());
                var time = refresh_html ? 0 : 500;
                
                setTimeout(function() {
                    let $chat_box = $('#chat-box');
                    let lastMsgPos = scrollTopOfBottom($chat_box)
                    
                    $('#loader').hide();

                    if (refresh_html) {
                        $('#chat-log').append(data);
                    }
                    else {
                        $('#chat-log').prepend(data);
                    }

                    $('.body-block').slice(0, window.messages_per_page).each(function() {
                    });

                    register_time($('.time-with-rel'));
                    merge_authors();

                    if (!refresh_html) {
                        $chat_box.scrollTop(scrollTopOfBottom($chat_box) - lastMsgPos);
                    }
                    else {
                        $('#chat-box').scrollTop($('#chat-box')[0].scrollHeight);
                    }
                    window.lock = false;
                }, time);
            })
    }

    function scrollTopOfBottom(container) {
        return container[0].scrollHeight - container.innerHeight()
    }

    function scrollContainer(container, loader) {
        container.scroll(function() {
        if (container.scrollTop() == 0) {
            if (currentPage < window.num_pages && !window.lock) {
                currentPage++;
                loader.show();
                load_page(currentPage);
            }
        }
    })}

    window.load_dynamic_update = function (last_msg) {
        var receiver = new EventReceiver(
            "{{ EVENT_DAEMON_LOCATION }}", "{{ EVENT_DAEMON_POLL_LOCATION }}",
            ['chat_lobby', 'chat_{{request.profile.id}}'], last_msg, function (message) {
                if (window.pushed_messages.has(message.message)) {
                    return;
                }
                window.pushed_messages.add(message.message);
                var room = (message.type == 'lobby') ? '' : message.room;
                if (message.author_id == {{request.profile.id}}) {
                    check_new_message(message.message, message.tmp_id, room);
                }
                else {
                    add_new_message(message.message, room, false);
                }
            }
        );

        return receiver;
    }

    function refresh_status() {
        $.get("{{url('online_status_ajax')}}")
            .fail(function() {
                console.log("Fail to get online status");
            })
            .done(function(data) {
                if (data.status == 403) {
                    console.log("Fail to retrieve data");
                }
                else {
                    $('#chat-online-list').html(data).find('.toggle').each(function () {
                        register_toggle($(this));
                    });
                    register_click_space();
                }
            })

        var data = {
            'user': window.other_user_id,
        };

        $.get("{{url('user_online_status_ajax')}}", data)
            .fail(function() {
                console.log("Fail to get user online status");
            })
            .done(function(data) {
                $('#chat-info').html(data);
                register_time($('.time-with-rel'));
                register_setting();
            })
    }

    function add_message(data) {
        var $data = $(data);

        $('#chat-log').append($data);
        $('#chat-box').scrollTop($('#chat-box')[0].scrollHeight);
        register_time($('.time-with-rel'));
        MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
        merge_authors();
    }

    function add_new_message(message, room, is_self_author) {
        function callback(update) {
            if (!document['hidden']) {
                if (update) update_last_seen();
                refresh_status();
            }
            else if (!is_self_author) {
                window.unread_message++;
                document.title = "(" + window.unread_message + ") " + "{{ _('New message(s)') }}";
            }
        }

        if (room == window.room_id) {
            $.get({
                url: "{{ url('chat_message_ajax') }}",
                data: {
                    message: message,
                },
                success: function (data) {
                    add_message(data);
                    callback(true);
                },
                error: function (data) {
                    console.log('Could not add new message');
                }
            });
        }
        else {
            callback(false);
        }
    }

    function check_new_message(message, tmp_id, room) {
        if (room == room_id) {
            $.get({
                url: "{{ url('chat_message_ajax') }}",
                data: {
                    message: message,
                },
                success: function (data) {
                    var $body_block = $(data).find('.body-block');
                    if ($('#message-'+tmp_id).length) {
                        $('#message-'+tmp_id).replaceWith(data);
                    }
                    else if ($('#body-block-'+tmp_id).length) {
                        $('#body-block-'+tmp_id).replaceWith($body_block);
                    }
                    else {
                        add_new_message(message, room, true);
                    }
                    MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
                    register_time($('.time-with-rel'));
                    remove_unread_current_user();
                    merge_authors();
                },
                error: function (data) {
                    console.log('Fail to check message');
                    var $body = $('#body-block-'+tmp_id + ' p');
                    $body.css('text-decoration', 'line-through');
                    $body.css('text-decoration-color', 'red');
                }
            });
        }
    }

    function merge_authors() {
        var time_limit = 5; // minutes
        var last = {
            username: null,
            time: null,
            $content: null
        };
        $('.body-message').each(function() {
            var username = $(this).find(".username a").text().trim();
            var $body = $(this).find(".content-message .body-block");
            var time = moment($(this).find(".time-with-rel").attr('data-iso'));
            var $content = $(this).children('.content-message');

            if (username == window.user.name) {
                $(this).find('.message-text').each(function() {
                    $(this).removeClass('message-text-other').addClass('message-text-myself');  
                });
            }

            if (username == last.username && time.diff(last.time, 'minutes') <= time_limit) {
                last.$content.append($body);
                $(this).parent().remove();
            }
            else {
                last.username = username;
                last.time = time;
                last.$content = $content;
            }
        });
    }

    function add_message_from_template(body, tmp_id) {
        var html = message_template;
        html = html.replaceAll('$body', body).replaceAll('$id', tmp_id);
        var $html = $(html);
        $html.find('.time-with-rel').attr('data-iso', (new Date()).toISOString());
        add_message($html[0].outerHTML);
    }

    function submit_chat() {
        {% if last_msg and not request.profile.mute %}
        if ($("#chat-input").val().trim()) {
            var body = $('#chat-input').val().trim();
            // body = body.split('\n').join('\n\n');
            
            var message = {
                body: body,
                room: window.room_id,
                tmp_id: Date.now(),
            };

            $('#chat-input').val('');

            add_message_from_template(body, message.tmp_id);

            $.post("{{ url('post_chat_message') }}", message)
                .fail(function(res) {
                    console.log('Fail to send message');
                })
                .done(function(res, status) {
                    $('#empty_msg').hide();
                    $('#chat-input').focus();
                })
        }
        {% endif %}
    }

    function resize_emoji(element) {
        var html = element.html();
        html = html.replace(/(\p{Extended_Pictographic})/ug, `<span class="big-emoji">$1</span>`);
        element.html(html);
    }

    function insert_char_after_cursor(elem, char) {
        var val = elem.value;
        if (typeof elem.selectionStart == "number" && typeof elem.selectionEnd == "number") {
            var start = elem.selectionStart;
            var prefix = elem.value.slice(0, start);
            var prefix_added = prefix + char;
            var chars = [...val];
            chars.splice([...prefix].length, 0, char);
            elem.value = chars.join('');
            elem.selectionStart = elem.selectionEnd = prefix_added.length;
        } else if (document.selection && document.selection.createRange) {
            var range = document.selection.createRange();
            elem.focus();
            range.text = char;
            range.collapse(false);
            range.select();
        }
    }

    function load_room(encrypted_user) {
        if (window.lock_click_space) return;

        function callback() {
            history.replaceState(null, '', "{{url('chat', '')}}" + window.room_id);
            load_page(window.currentPage, true, refresh_status);
            update_last_seen();
            refresh_status();
            $('#chat-input').focus();
        }
        window.lock_click_space = true;
        if (encrypted_user) {
            $.get("{{url('get_or_create_room')}}" + `?other=${encrypted_user}`)
                .done(function(data) {
                    window.currentPage = 1;
                    window.room_id = data.room;
                    window.other_user_id = data.other_user_id;
                    callback();
                })
                .fail(function() {
                    console.log('Fail to get_or_create_room');
                })
        }
        else {
            window.currentPage = 1;
            window.room_id = '';
            window.other_user_id = '';
            callback();
        }
        window.lock_click_space = false;
    }

    function register_click_space() {
        $('.click_space').on('click', function(e) {
            if ($(this).attr('id') == 'click_space_' + window.other_user_id) {
                return;
            }
            var other_user = $(this).attr('value');
            load_room(other_user);
        });
        $('#lobby_row').on('click', function(e) {
            if (window.room_id) {
                load_room(null);
            }
        });
        if (isMobile) {
            $('#chat-tab a').click();
        }
    }

    function update_last_seen() {
        var data = {
            room: window.room_id
        };

        $.post("{{ url('update_last_seen') }}", data)
            .fail(function(data) {
                console.log('Fail to update last seen');
            })
            .done(function(data) {

            })
    }

    function remove_unread_current_user() {
        if (window.other_user_id) {
           $("#unread-count-" + window.other_user_id).hide();
        }
        else {
            $('#unread-count-lobby').hide();
        }
    }

    function register_setting() {
        $('#setting-button').on('click', function() {
            $('#setting-content').toggle();
        });
        $('#setting-content li').on('click', function() {
            $(this).children('a')[0].click();
        })
        $('#setting-content a').on('click', function() {
            var href = $(this).attr('href');
            href += '?next=' + window.location.pathname;
            $(this).attr('href', href);
        })
    }

    $(function() {
        $('#loader').hide();
        merge_authors();

        scrollContainer($('#chat-box'), $('#loader'))

        {% if request.user.is_staff %}
        $(document).on("click", ".chatbtn_remove_mess", function() {
            var elt = $(this);
            $.ajax({
                url: "{{ url('delete_chat_message') }}",
                type: 'post',
                data: {
                    message: elt.attr('value'),
                },
                dataType: 'json',
                success: function(data){
                    var $block = elt.parent();
                    if ($block.parent().find('.body-block').length > 1) {
                        $block.remove();
                    }
                    else {
                        elt.closest('li').remove();
                    }
                },
                fail: function(data) {
                    console.log('Fail to delete');
                },
            });
        });
        {% endif %}
        
        $("#chat-log").show();
        $("#chat-log").change(function() {
            $('#chat-log').scrollTop($('#chat-log')[0].scrollHeight);
        });
        
        $('#chat-input').focus();

        $('#chat-input').keydown(function(e) {
            if (e.keyCode === 13) {
                if (e.ctrlKey || e.shiftKey) {
                    insert_char_after_cursor(this, "\n");
                }
                else {
                    e.preventDefault();
                    submit_chat();
                }
                return false
            }
            return true
        });

        $('.chat-right-panel').hide();
        $('#chat-tab').find('a').click(function (e) {
            e.preventDefault();
            $('#chat-tab').addClass('active');
            $('#online-tab').removeClass('active');
            $('.chat-left-panel').show();
            $('.chat-right-panel').hide();
        });
        $('#online-tab').find('a').click(function (e) {
            e.preventDefault();
            $('#online-tab').addClass('active');
            $('#chat-tab').removeClass('active');
            $('.chat-left-panel').hide();
            $('.chat-right-panel').show();
        });

        $('#refresh-button').on('click', function(e) {
            e.preventDefault();
            refresh_status();
        });

        setInterval(refresh_status, 2 * 60 * 1000);

        $('#chat-box').scrollTop($('#chat-box')[0].scrollHeight);
        load_dynamic_update({{last_msg}});

        const button = document.querySelector('#emoji-button')
        const tooltip = document.querySelector('.tooltip')
        Popper.createPopper(button, tooltip)

        function toggleEmoji() {
            tooltip.classList.toggle('shown')
        }
        $('#emoji-button').on('click', function(e) {
            e.preventDefault();
            toggleEmoji();
        });

        $('emoji-picker').on('emoji-click', function(e) {
            var $chat = $('#chat-input').get(0);
            insert_char_after_cursor($chat, e.detail.unicode);
            $chat.focus();
        })

        register_click_space();

        document.addEventListener('keydown', function(e) {
            if (e.keyCode === 27 && $('.tooltip').hasClass('shown')) {
                toggleEmoji();
            }
        })
        
        $('#search-handle').replaceWith($('<select>').attr({
            id: 'search-handle',
            name: 'other',
            onchange: 'form.submit()'
        }));

        var in_user_redirect = false;
        $('#search-handle').select2({
            placeholder: '{{ _('Search by handle...') }}',
            ajax: {
                url: '{{ url('chat_user_search_select2_ajax') }}'
            },
            minimumInputLength: 1,
            escapeMarkup: function (markup) {
                return markup;
            },
            templateResult: function (data, container) {
                return $('<span>')
                    .append($('<img>', {
                        'class': 'user-search-image', src: data.gravatar_url,
                        width: 24, height: 24
                    }))
                    .append($('<span>', {'class': data.display_rank + ' user-search-name'}).text(data.text))
                    .append($('<a>', {href: '/user/' + data.text, 'class': 'user-redirect'})
                        .append($('<i>', {'class': 'fa fa-mail-forward'}))
                        .mouseover(function () {
                            in_user_redirect = true;
                        }).mouseout(function () {
                            in_user_redirect = false;
                        }));
            }
        }).on('select2:selecting', function () {
            return !in_user_redirect;
        });

        // https://stackoverflow.com/questions/42121565/detecting-class-change-without-setinterval
        if (typeof(MutationObserver) !== undefined) {
            var observer = new MutationObserver(function (event) {
                if (!document['hidden'] && window.unread_message > 0) {
                    update_last_seen();
                    refresh_status();
                    window.unread_message = 0;
                    document.title = "{{_('Chat Box')}}";
                }
            })
            
            observer.observe(document.body, {
                attributes: true, 
                attributeFilter: ['class'],
                childList: false, 
                characterData: false
            })
        }
        register_setting();
    });
</script>

{% endblock js_media %}

{% block media %}
    {% include "chat/chat_css.html" %}
{% endblock media %}
{% block footer %}{% endblock %}
{% block body %}
    <div id="mobile" class="tabs">
        <ul>
            <li id="chat-tab" class="tab active"><a href="#">
                <i class="tab-icon fa fa-comments"></i> {{ _('Chat') }}
            </a></li>
            <li id="online-tab" class="tab"><a href="#"><i class="tab-icon fa fa-wifi"></i> {{ _('Online Users') }}</a></li>
        </ul>
    </div>
    
    <div id="chat-container">
        <div id="chat-online" class="chat-right-panel sidebox">
            <h3 style="display:flex">
                {{_('Online Users')}}
                <a href="#" id="refresh-button" title="{{_('Refresh')}}">
                    <img src="/reload.png"
                         width="100%"
                    >
                </a> 
            </h3>
            <div id="chat-online-content">
                <div id="search-container">
                    <center>
                        <form id="search-form" name="form" action="{{ url('get_or_create_room') }}" method="post">
                            {% csrf_token %}
                            <input id="search-handle" type="text" name="search"
                                   placeholder="{{ _('Search by handle...') }}">
                        </form>
                    </center>
                </div>
                <div id="chat-online-list">
                    {% include "chat/online_status.html" %}
                </div>
            </div>
        </div>
        <div id="chat-area" class="chat-left-panel" style="width:100%">
                <div id="chat-info" style="height: 8%">
                    {% include 'chat/user_online_status.html' %}
                </div>
                <div id="chat-box">

                    <img src="{{static('loading.gif')}}" id="loader">
                    <ul id="chat-log" style="display: none">
                        {% include 'chat/message_list.html' %}
                    </ul>
                </div>
                <div style="height: 15%">
                    <a id="emoji-button" href="#" title="{{_('Emoji')}}"><i class="icofont-slightly-smile"></i></a>
                    <textarea maxlength="5000" id="chat-input" placeholder="{{_('Enter your message')}}"></textarea>
                </div>
                <div class="tooltip" role="tooltip">
                    <emoji-picker></emoji-picker>
                </div>
        </div>
    </div>
{% endblock body %}