{% set layout = "no_wrapper" %}
{% 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('mathjax3_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.limit_time = 24;
    window.room_id = "{{room if room else ''}}";
    window.unread_message = 0;
    window.other_user_id = "{{other_user.id if other_user else ''}}";
    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_next_page(last_id, refresh_html=false) {
      var param = {
        'last_id': last_id,
        'only_messages': true,
      }
      $.get("{{ url('chat', '') }}" + window.room_id, param)
        .fail(function() {
        console.log("Fail to load page, last_id = " + last_id);
      })
        .done(function(data) {
        if (refresh_html) {
          $('#chat-log').html('');
          $('#chat-box').scrollTop($('#chat-box')[0].scrollHeight);
          window.lock = true;
        }
        var time = refresh_html ? 0 : 200;

        setTimeout(function() {
          $(".has_next").remove();
          let $chat_box = $('#chat-box');
          let lastMsgPos = scrollTopOfBottom($chat_box)

          $('#loader').hide();

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

          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;
          window.has_next = parseInt($(".has_next").attr("value"));
        }, time);
      })
    }

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

    function scrollContainer(container, loader) {
      container.scroll(function() {
        if (container.scrollTop() == 0) {
          if (!window.lock && window.has_next) {
            loader.show();
            var message_ids = $('.message').map(function() {
              return parseInt($(this).attr('message-id'));
            }).get();
            load_next_page(Math.min(...message_ids));
          }
        }
      })}

    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.typeset();
      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.typeset();
            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_next_page(null, true);
        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.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.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();
      window.has_next = parseInt($(".has_next").attr("value"));

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

      {% if request.user.is_staff %}
        $(document).on("click", ".chat_remove", 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');
            },
          });
        });
        $(document).on("click", ".chat_mute", function() {
          if (confirm("{{_('Mute this user and delete all messages?')}}")) {
            var elt = $(this);
            $.ajax({
              url: "{{ url('mute_chat_message') }}",
              type: 'post',
              data: {
                message: elt.attr('value'),
              },
              dataType: 'json',
              success: function(data){
                window.location.reload();
              },
              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;
      });

      $("#chat-input").on("keyup", function() {
        $("#chat-input").scrollTop($("#chat-input")[0].scrollHeight);
      });

      // 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 body %}
  <div class="chat">
    <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>
          <i class="fa fa-users"></i>{{_('Online Users')}}
        </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: 10%">
          {% 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>
  </div>
{% endblock body %}
