/**
 * Comments.
 */

import { $ } from './utils/dom';
import { showOwnedComments } from './communications/comment';
import { filterNode } from './imagesclientside';
import { fetchHtml } from './utils/requests';

function handleError(response) {

  const errorMessage = '<div>Comment failed to load!</div>';

  if (!response.ok) {
    return errorMessage;
  }
  return response.text();

}

function commentPosted(response) {

  const commentEditTab  = $('#js-comment-form a[data-click-tab="write"]'),
        commentEditForm = $('#js-comment-form'),
        container       = document.getElementById('comments'),
        requestOk       = response.ok;

  commentEditTab.click();
  commentEditForm.reset();

  if (requestOk) {
    response.text().then(text => displayComments(container, text));
  }
  else {
    window.location.reload();
    window.scrollTo(0, 0); // Error message is displayed at the top of the page (flash)
  }

}

function loadParentPost(event) {

  const clickedLink = event.target,
        // Find the comment containing the link that was clicked
        fullComment = clickedLink.closest('article.block'),
        // Look for a potential image and comment ID
        commentMatches = /(\w+)#comment_(\w+)$/.exec(clickedLink.getAttribute('href'));

  // If the clicked link is already active, just clear the parent comments
  if (clickedLink.classList.contains('active_reply_link')) {
    clearParentPost(clickedLink, fullComment);

    return true;
  }

  if (commentMatches) {

    // If the regex matched, get the image and comment ID
    const [ , imageId, commentId ] = commentMatches;

    fetchHtml(`/images/${imageId}/comments/${commentId}`)
      .then(handleError)
      .then(data => {
        clearParentPost(clickedLink, fullComment);
        insertParentPost(data, clickedLink, fullComment);
      });

    return true;

  }

}

function insertParentPost(data, clickedLink, fullComment) {

  // Add the 'subthread' class to the comment with the clicked link
  fullComment.classList.add('subthread');

  // Insert parent comment
  fullComment.insertAdjacentHTML('beforebegin', data);

  // Add class subthread and fetched-comment - use separate add()-methods to support IE11
  fullComment.previousSibling.classList.add('subthread');
  fullComment.previousSibling.classList.add('fetched-comment');

  // Execute timeago on the new comment - it was not present when first run
  window.booru.timeAgo(fullComment.previousSibling.getElementsByTagName('time'));

  // Add class active_reply_link to the clicked link
  clickedLink.classList.add('active_reply_link');

  // Filter images (if any) in the loaded comment
  filterNode(fullComment.previousSibling);

}

function clearParentPost(clickedLink, fullComment) {

  // Remove any previous siblings with the class fetched-comment
  while (fullComment.previousSibling && fullComment.previousSibling.classList.contains('fetched-comment')) {
    fullComment.previousSibling.parentNode.removeChild(fullComment.previousSibling);
  }

  // Remove class active_reply_link from all links in the comment
  [].slice.call(fullComment.getElementsByClassName('active_reply_link')).forEach(link => {
    link.classList.remove('active_reply_link');
  });

  // If this full comment isn't a fetched comment, remove the subthread class.
  if (!fullComment.classList.contains('fetched-comment')) {
    fullComment.classList.remove('subthread');
  }

}

function displayComments(container, commentsHtml) {

  container.innerHTML = commentsHtml;

  // Execute timeago on comments
  window.booru.timeAgo(document.getElementsByTagName('time'));

  // Filter images in the comments
  filterNode(container);

  // Show options on own comments
  showOwnedComments();

}

function loadComments(event) {

  const container = document.getElementById('comments'),
        hasHref = event.target && event.target.getAttribute('href'),
        hasHash = window.location.hash && window.location.hash.match(/#comment_([a-f0-9]+)/),
        getURL = hasHref || (hasHash ? `${container.dataset.currentUrl}?comment_id=${window.location.hash.substring(9, window.location.hash.length)}`
          : container.dataset.currentUrl);

  fetchHtml(getURL)
    .then(handleError)
    .then(data => {

      displayComments(container, data);

      // Make sure the :target CSS selector applies to the inserted content
      // https://bugs.chromium.org/p/chromium/issues/detail?id=98561
      if (hasHash) {
        // eslint-disable-next-line
        window.location = window.location;
      }
    });

  return true;

}

function setupComments() {
  const comments     = document.getElementById('comments'),
        hasHash      = window.location.hash && window.location.hash.match(/^#comment_([a-f0-9]+)$/),
        targetOnPage = hasHash ? Boolean($(window.location.hash)) : true;

  // Load comments over AJAX if we are on a page with element #comments
  if (comments) {
    if (!comments.dataset.loaded || !targetOnPage) {
      // There is no event associated with the initial load, so use false
      loadComments(false);
    }
    else {
      filterNode(comments);
      showOwnedComments();
    }
  }

  // Define clickable elements and the function to execute on click
  const targets = {
    'article[id*="comment"] .communication__body__text a[href]': loadParentPost,
    '#comments .pagination a[href]': loadComments,
    '#js-refresh-comments': loadComments,
  };

  document.addEventListener('click', event => {
    if (event.button === 0) { // Left-click only
      for (const target in targets) {
        if (event.target && event.target.closest(target)) {
          targets[target](event) && event.preventDefault();
        }
      }
    }
  });

  document.addEventListener('fetchcomplete', event => {
    if (event.target.id === 'js-comment-form') commentPosted(event.detail);
  });
}

export { setupComments };