import $ from 'jquery';
import {
  initRepoIssueBranchSelect, initRepoIssueCodeCommentCancel, initRepoIssueCommentDelete,
  initRepoIssueComments, initRepoIssueDependencyDelete, initRepoIssueReferenceIssue,
  initRepoIssueTitleEdit, initRepoIssueWipToggle,
  initRepoPullRequestUpdate, updateIssuesMeta, handleReply, initIssueTemplateCommentEditors, initSingleCommentEditor,
} from './repo-issue.js';
import {initUnicodeEscapeButton} from './repo-unicode-escape.js';
import {svg} from '../svg.js';
import {htmlEscape} from 'escape-goat';
import {initRepoBranchTagSelector} from '../components/RepoBranchTagSelector.vue';
import {
  initRepoCloneLink, initRepoCommonBranchOrTagDropdown, initRepoCommonFilterSearchDropdown,
  initRepoCommonLanguageStats,
} from './repo-common.js';
import {initCitationFileCopyContent} from './citation.js';
import {initCompLabelEdit} from './comp/LabelEdit.js';
import {initRepoDiffConversationNav} from './repo-diff.js';
import {createDropzone} from './dropzone.js';
import {initCommentContent, initMarkupContent} from '../markup/content.js';
import {initCompReactionSelector} from './comp/ReactionSelector.js';
import {initRepoSettingBranches} from './repo-settings.js';
import {initRepoPullRequestMergeForm} from './repo-issue-pr-form.js';
import {hideElem, showElem} from '../utils/dom.js';
import {getComboMarkdownEditor, initComboMarkdownEditor} from './comp/ComboMarkdownEditor.js';
import {attachRefIssueContextPopup} from './contextpopup.js';
const {csrfToken} = window.config;
// if there are draft comments, confirm before reloading, to avoid losing comments
function reloadConfirmDraftComment() {
  const commentTextareas = [
    document.querySelector('.edit-content-zone:not(.gt-hidden) textarea'),
    document.querySelector('#comment-form textarea'),
  ];
  for (const textarea of commentTextareas) {
    // Most users won't feel too sad if they lose a comment with 10 chars, they can re-type these in seconds.
    // But if they have typed more (like 50) chars and the comment is lost, they will be very unhappy.
    if (textarea && textarea.value.trim().length > 10) {
      textarea.parentElement.scrollIntoView();
      if (!window.confirm('Page will be reloaded, but there are draft comments. Continuing to reload will discard the comments. Continue?')) {
        return;
      }
      break;
    }
  }
  window.location.reload();
}
export function initRepoCommentForm() {
  const $commentForm = $('.comment.form');
  if ($commentForm.length === 0) {
    return;
  }
  if ($commentForm.find('.field.combo-editor-dropzone').length) {
    // at the moment, if a form has multiple combo-markdown-editors, it must be a issue template form
    initIssueTemplateCommentEditors($commentForm);
  } else {
    initSingleCommentEditor($commentForm);
  }
  function initBranchSelector() {
    const $selectBranch = $('.ui.select-branch');
    const $branchMenu = $selectBranch.find('.reference-list-menu');
    const $isNewIssue = $branchMenu.hasClass('new-issue');
    $branchMenu.find('.item:not(.no-select)').on('click', function () {
      const selectedValue = $(this).data('id');
      const editMode = $('#editing_mode').val();
      $($(this).data('id-selector')).val(selectedValue);
      if ($isNewIssue) {
        $selectBranch.find('.ui .branch-name').text($(this).data('name'));
        return;
      }
      if (editMode === 'true') {
        const form = $('#update_issueref_form');
        $.post(form.attr('action'), {_csrf: csrfToken, ref: selectedValue}, () => window.location.reload());
      } else if (editMode === '') {
        $selectBranch.find('.ui .branch-name').text(selectedValue);
      }
    });
    $selectBranch.find('.reference.column').on('click', function () {
      hideElem($selectBranch.find('.scrolling.reference-list-menu'));
      $selectBranch.find('.reference .text').removeClass('black');
      showElem($($(this).data('target')));
      $(this).find('.text').addClass('black');
      return false;
    });
  }
  initBranchSelector();
  // List submits
  function initListSubmits(selector, outerSelector) {
    const $list = $(`.ui.${outerSelector}.list`);
    const $noSelect = $list.find('.no-select');
    const $listMenu = $(`.${selector} .menu`);
    let hasUpdateAction = $listMenu.data('action') === 'update';
    const items = {};
    $(`.${selector}`).dropdown({
      'action': 'nothing', // do not hide the menu if user presses Enter
      fullTextSearch: 'exact',
      async onHide() {
        hasUpdateAction = $listMenu.data('action') === 'update'; // Update the var
        if (hasUpdateAction) {
          // TODO: Add batch functionality and make this 1 network request.
          const itemEntries = Object.entries(items);
          for (const [elementId, item] of itemEntries) {
            await updateIssuesMeta(
              item['update-url'],
              item.action,
              item['issue-id'],
              elementId,
            );
          }
          if (itemEntries.length) {
            reloadConfirmDraftComment();
          }
        }
      },
    });
    $listMenu.find('.item:not(.no-select)').on('click', function (e) {
      e.preventDefault();
      if ($(this).hasClass('ban-change')) {
        return false;
      }
      hasUpdateAction = $listMenu.data('action') === 'update'; // Update the var
      const clickedItem = $(this);
      const scope = $(this).attr('data-scope');
      $(this).parent().find('.item').each(function () {
        if (scope) {
          // Enable only clicked item for scoped labels
          if ($(this).attr('data-scope') !== scope) {
            return true;
          }
          if (!$(this).is(clickedItem) && !$(this).hasClass('checked')) {
            return true;
          }
        } else if (!$(this).is(clickedItem)) {
          // Toggle for other labels
          return true;
        }
        if ($(this).hasClass('checked')) {
          $(this).removeClass('checked');
          $(this).find('.octicon-check').addClass('invisible');
          if (hasUpdateAction) {
            if (!($(this).data('id') in items)) {
              items[$(this).data('id')] = {
                'update-url': $listMenu.data('update-url'),
                action: 'detach',
                'issue-id': $listMenu.data('issue-id'),
              };
            } else {
              delete items[$(this).data('id')];
            }
          }
        } else {
          $(this).addClass('checked');
          $(this).find('.octicon-check').removeClass('invisible');
          if (hasUpdateAction) {
            if (!($(this).data('id') in items)) {
              items[$(this).data('id')] = {
                'update-url': $listMenu.data('update-url'),
                action: 'attach',
                'issue-id': $listMenu.data('issue-id'),
              };
            } else {
              delete items[$(this).data('id')];
            }
          }
        }
      });
      // TODO: Which thing should be done for choosing review requests
      // to make chosen items be shown on time here?
      if (selector === 'select-reviewers-modify' || selector === 'select-assignees-modify') {
        return false;
      }
      const listIds = [];
      $(this).parent().find('.item').each(function () {
        if ($(this).hasClass('checked')) {
          listIds.push($(this).data('id'));
          $($(this).data('id-selector')).removeClass('gt-hidden');
        } else {
          $($(this).data('id-selector')).addClass('gt-hidden');
        }
      });
      if (listIds.length === 0) {
        $noSelect.removeClass('gt-hidden');
      } else {
        $noSelect.addClass('gt-hidden');
      }
      $($(this).parent().data('id')).val(listIds.join(','));
      return false;
    });
    $listMenu.find('.no-select.item').on('click', function (e) {
      e.preventDefault();
      if (hasUpdateAction) {
        updateIssuesMeta(
          $listMenu.data('update-url'),
          'clear',
          $listMenu.data('issue-id'),
          '',
        ).then(reloadConfirmDraftComment);
      }
      $(this).parent().find('.item').each(function () {
        $(this).removeClass('checked');
        $(this).find('.octicon-check').addClass('invisible');
      });
      if (selector === 'select-reviewers-modify' || selector === 'select-assignees-modify') {
        return false;
      }
      $list.find('.item').each(function () {
        $(this).addClass('gt-hidden');
      });
      $noSelect.removeClass('gt-hidden');
      $($(this).parent().data('id')).val('');
    });
  }
  // Init labels and assignees
  initListSubmits('select-label', 'labels');
  initListSubmits('select-assignees', 'assignees');
  initListSubmits('select-assignees-modify', 'assignees');
  initListSubmits('select-reviewers-modify', 'assignees');
  function selectItem(select_id, input_id) {
    const $menu = $(`${select_id} .menu`);
    const $list = $(`.ui${select_id}.list`);
    const hasUpdateAction = $menu.data('action') === 'update';
    $menu.find('.item:not(.no-select)').on('click', function () {
      $(this).parent().find('.item').each(function () {
        $(this).removeClass('selected active');
      });
      $(this).addClass('selected active');
      if (hasUpdateAction) {
        updateIssuesMeta(
          $menu.data('update-url'),
          '',
          $menu.data('issue-id'),
          $(this).data('id'),
        ).then(reloadConfirmDraftComment);
      }
      let icon = '';
      if (input_id === '#milestone_id') {
        icon = svg('octicon-milestone', 18, 'gt-mr-3');
      } else if (input_id === '#project_id') {
        icon = svg('octicon-project', 18, 'gt-mr-3');
      } else if (input_id === '#assignee_id') {
        icon = ``;
      }
      $list.find('.selected').html(`
        
          ${icon}
          ${htmlEscape($(this).text())}
        
      `);
      $(`.ui${select_id}.list .no-select`).addClass('gt-hidden');
      $(input_id).val($(this).data('id'));
    });
    $menu.find('.no-select.item').on('click', function () {
      $(this).parent().find('.item:not(.no-select)').each(function () {
        $(this).removeClass('selected active');
      });
      if (hasUpdateAction) {
        updateIssuesMeta(
          $menu.data('update-url'),
          '',
          $menu.data('issue-id'),
          $(this).data('id'),
        ).then(reloadConfirmDraftComment);
      }
      $list.find('.selected').html('');
      $list.find('.no-select').removeClass('gt-hidden');
      $(input_id).val('');
    });
  }
  // Milestone, Assignee, Project
  selectItem('.select-project', '#project_id');
  selectItem('.select-milestone', '#milestone_id');
  selectItem('.select-assignee', '#assignee_id');
}
async function onEditContent(event) {
  event.preventDefault();
  const $segment = $(this).closest('.header').next();
  const $editContentZone = $segment.find('.edit-content-zone');
  const $renderContent = $segment.find('.render-content');
  const $rawContent = $segment.find('.raw-content');
  let comboMarkdownEditor;
  const setupDropzone = async ($dropzone) => {
    if ($dropzone.length === 0) return null;
    let disableRemovedfileEvent = false; // when resetting the dropzone (removeAllFiles), disable the "removedfile" event
    let fileUuidDict = {}; // to record: if a comment has been saved, then the uploaded files won't be deleted from server when clicking the Remove in the dropzone
    const dz = await createDropzone($dropzone[0], {
      url: $dropzone.attr('data-upload-url'),
      headers: {'X-Csrf-Token': csrfToken},
      maxFiles: $dropzone.attr('data-max-file'),
      maxFilesize: $dropzone.attr('data-max-size'),
      acceptedFiles: (['*/*', ''].includes($dropzone.attr('data-accepts'))) ? null : $dropzone.attr('data-accepts'),
      addRemoveLinks: true,
      dictDefaultMessage: $dropzone.attr('data-default-message'),
      dictInvalidFileType: $dropzone.attr('data-invalid-input-type'),
      dictFileTooBig: $dropzone.attr('data-file-too-big'),
      dictRemoveFile: $dropzone.attr('data-remove-file'),
      timeout: 0,
      thumbnailMethod: 'contain',
      thumbnailWidth: 480,
      thumbnailHeight: 480,
      init() {
        this.on('success', (file, data) => {
          file.uuid = data.uuid;
          fileUuidDict[file.uuid] = {submitted: false};
          const input = $(``).val(data.uuid);
          $dropzone.find('.files').append(input);
        });
        this.on('removedfile', (file) => {
          if (disableRemovedfileEvent) return;
          $(`#${file.uuid}`).remove();
          if ($dropzone.attr('data-remove-url') && !fileUuidDict[file.uuid].submitted) {
            $.post($dropzone.attr('data-remove-url'), {
              file: file.uuid,
              _csrf: csrfToken,
            });
          }
        });
        this.on('submit', () => {
          $.each(fileUuidDict, (fileUuid) => {
            fileUuidDict[fileUuid].submitted = true;
          });
        });
        this.on('reload', () => {
          $.getJSON($editContentZone.attr('data-attachment-url'), (data) => {
            // do not trigger the "removedfile" event, otherwise the attachments would be deleted from server
            disableRemovedfileEvent = true;
            dz.removeAllFiles(true);
            $dropzone.find('.files').empty();
            fileUuidDict = {};
            disableRemovedfileEvent = false;
            for (const attachment of data) {
              const imgSrc = `${$dropzone.attr('data-link-url')}/${attachment.uuid}`;
              dz.emit('addedfile', attachment);
              dz.emit('thumbnail', attachment, imgSrc);
              dz.emit('complete', attachment);
              dz.files.push(attachment);
              fileUuidDict[attachment.uuid] = {submitted: true};
              $dropzone.find(`img[src='${imgSrc}']`).css('max-width', '100%');
              const input = $(``).val(attachment.uuid);
              $dropzone.find('.files').append(input);
            }
          });
        });
      },
    });
    dz.emit('reload');
    return dz;
  };
  const cancelAndReset = (dz) => {
    showElem($renderContent);
    hideElem($editContentZone);
    if (dz) {
      dz.emit('reload');
    }
  };
  const saveAndRefresh = (dz, $dropzone) => {
    showElem($renderContent);
    hideElem($editContentZone);
    const $attachments = $dropzone.find('.files').find('[name=files]').map(function () {
      return $(this).val();
    }).get();
    $.post($editContentZone.attr('data-update-url'), {
      _csrf: csrfToken,
      content: comboMarkdownEditor.value(),
      context: $editContentZone.attr('data-context'),
      files: $attachments,
    }, (data) => {
      if (!data.content) {
        $renderContent.html($('#no-content').html());
        $rawContent.text('');
      } else {
        $renderContent.html(data.content);
        $rawContent.text(comboMarkdownEditor.value());
        const refIssues = $renderContent.find('p .ref-issue');
        attachRefIssueContextPopup(refIssues);
      }
      const $content = $segment;
      if (!$content.find('.dropzone-attachments').length) {
        if (data.attachments !== '') {
          $content.append(`