<template>
  <aside id="comments-container" aria-labelledby="comments-label">
    <h2 id="comments-label" class="sr-only">Commentaires</h2>
    <div
      class="comments | flow"
      :class="{ empty: !comments || comments.length === 0 }"
    >
      <template v-if="comments">
        <template v-if="!openedComment">
          <Comment
            v-for="(comment, commentIndex) in sortedComments"
            :comment="comment"
            :commentIndex="comments.length - commentIndex"
            :key="comment.id"
            @click="openComment(comment)"
            @update:file="changeFile"
            @close:comment="closeComment"
          />
        </template>
        <template v-else>
          <button
            class="btn | justify-start w-full | bg-white-10 text-white | px-8"
            data-icon="chevron-single-left"
            @click="
              openedComment = null;
              isAddOpen = false;
            "
          >
            <span>Retour à la liste</span>
          </button>
          <Comment
            :comment="openedComment"
            data-opened="true"
            @update:file="changeFile"
            @close:comment="closeComment"
          />
          <div v-if="sortedReplies.length > 0" class="replies | flow">
            <Comment
              v-for="(reply, commentIndex) in sortedReplies"
              :comment="reply"
              :commentIndex="sortedReplies.length - commentIndex"
              :key="reply.id"
              @update:file="changeFile"
              @close:comment="closeComment"
            />
          </div>
        </template>
      </template>
    </div>
    <button
      v-if="!openedComment && !isAddOpen"
      id="create-comment"
      class="btn btn--white-20 | w-full"
      @click="toggleCommentPositionMode(true)"
    >
      Ajouter un commentaire
    </button>
    <button
      v-else-if="openedComment && !isAddOpen"
      id="reply-comment"
      class="btn btn--white-20 | justify-start w-full | text-white-50"
      @click="isAddOpen = true"
    >
      Répondre…
    </button>
    <!-- TODO: afficher #new-comment une fois le bouton Ajouter un commentaire cliqué -->
    <div
      v-if="waitingForCommentPosition"
      id="new-comment"
      class="bg-primary | text-sm text-white | rounded-lg | p-12"
    >
      <p class="flex justify-start | mb-12" data-icon="comment">
        <strong>Nouveau commentaire</strong>
      </p>
      <p>
        Dans la zone du contenu, cliquez où vous souhaitez positionner le
        commentaire
      </p>
    </div>
    <form
      v-if="isAddOpen"
      action=""
      method="post"
      class="flow | p-12 | rounded-xl"
      @submit="handleSubmit"
    >
      <label class="sr-only" for="comment">Votre commentaire</label>
      <textarea
        v-model="draftComment.text"
        :disabled="isSubmitting ? true : undefined"
        name="comment"
        id="comment"
        placeholder="Ajouter un commentaire…"
        rows="5"
        class="text-sm | rounded-lg bg-black p-12"
      ></textarea>
      <footer class="flex">
        <input
          type="submit"
          class="btn"
          :class="{ submitting: isSubmitting }"
          :value="isSubmitting ? 'En cours' : undefined"
          :disabled="isSubmitting ? true : undefined"
        />
        <button class="btn btn--white-10" @click="isAddOpen = false">
          Annuler
        </button>
      </footer>
    </form>
  </aside>
</template>

<script setup>
import dayjs from 'dayjs';
import 'dayjs/locale/fr';
import uniqid from 'uniqid';
import { watch, ref, computed } from 'vue';
import { useUserStore } from '../../stores/user';
import { usePageStore } from '../../stores/page';
import { useApiStore } from '../../stores/api';
import { useDialogStore } from '../../stores/dialog';
import Comment from './Comment.vue';
import { storeToRefs } from 'pinia';
import { useRoute } from 'vue-router';

dayjs.locale('fr');

const { user } = useUserStore();
const { page } = usePageStore();
const dialog = useDialogStore();
const { comments, openedFile, openedComment, draftComment, activeTracks } =
  storeToRefs(useDialogStore());
const api = useApiStore();

const isAddOpen = ref(false);
const route = useRoute();
const waitingForCommentPosition = ref(false);
const isSubmitting = ref(false);

const sortedComments = computed(() => {
  return [...comments.value].reverse();
});
const sortedReplies = ref(null);

watch(openedComment, (newVal) => {
  sortedReplies.value = newVal ? newVal.replies.slice().reverse() : null;

  if (!newVal) {
    unhighlightAllComments();
  }
});

watch(isAddOpen, (newVal) => {
  if (newVal) {
    setTimeout(() => {
      document.querySelector('textarea#comment').focus();
    }, 100);
  }
});

const viewContainer =
  openedFile.value?.type === 'document'
    ? document.querySelector('.vpv-pages-inner-container')
    : document.querySelector('.track');

window.addEventListener('keydown', (event) => {
  if (
    isAddOpen.value &&
    event.key === 'Enter' &&
    (event.metaKey || event.ctrlKey)
  ) {
    handleSubmit();
  }
});

// Functions
function unhighlightAllComments() {
  document.querySelectorAll('.comment-marker.big').forEach((commentNode) => {
    commentNode.classList.remove('big');
    commentNode.classList.remove('active');
  });
}

function handleSubmit(event = null) {
  if (event) {
    event.preventDefault();
  }
  const date = dayjs().format();
  const newComment = {
    fileName: openedFile.value ? openedFile.value.name : false,
    userUuid: user.uuid,
    text: draftComment.value.text,
    date,
    position: {
      pageIndex: openedComment.value
        ? openedComment.value.position.pageIndex
        : draftComment.value.position.pageIndex,
      x: openedComment.value ? false : draftComment.value.position.x,
      y: openedComment.value ? false : draftComment.value.position.y,
    },
    id: uniqid(),
  };
  if (openedComment.value) {
    replyComment(newComment);
  } else {
    addComment(newComment);
  }
}

async function replyComment(newComment) {
  newComment.parentId = openedComment.value.id;
  const matchFileParentUri = openedFile.value.url.match(
    /projects\/.*?(?=\/[^/]+\/[^/]+$)/
  );
  newComment.fileParentUri = matchFileParentUri ? matchFileParentUri[0] : null;
  const newFile = await api.replyComment(newComment);
  resetDraftComment();
  isAddOpen.value = false;
  dialog.updateFile(newFile);
  openedComment.value = newFile.comments.find(
    (item) => item.id === openedComment.value.id
  );
}

async function addComment(newComment) {
  const matchFileParentUri = openedFile.value.url.match(
    /projects\/.*?(?=\/[^/]+\/[^/]+$)/
  );
  newComment.fileParentUri = matchFileParentUri ? matchFileParentUri[0] : null;
  isSubmitting.value = true;
  const newFile = await api.addComment(newComment);
  isSubmitting.value = false;
  resetDraftComment();
  isAddOpen.value = false;
  if (!newFile) return;
  dialog.updateFile(newFile);
  if (activeTracks.value) {
    activeTracks.value = activeTracks.value.map((track) => {
      if (track.files) {
        track.files = track.files.map((file) =>
          file.uuid === newFile.uuid ? newFile : file
        );
      }
      return track;
    });
  }
}

function resetDraftComment() {
  draftComment.value.text = '';
  draftComment.value.position = null;
  draftComment.value.padeIndex = null;
}

function closeComment() {
  openedComment.value = null;
}

function toggleCommentPositionMode(enable) {
  if (enable) {
    waitingForCommentPosition.value = true;
    viewContainer.classList.add('waiting-comment');
    viewContainer.addEventListener('click', handleCommentPositionClick);
  } else {
    waitingForCommentPosition.value = false;
    viewContainer.classList.remove('waiting-comment');
    viewContainer.removeEventListener('click', handleCommentPositionClick);
  }
}

function handleCommentPositionClick(event) {
  if (openedFile.value.type === 'document') {
    prepareDraftCommentInPdf(event);
  } else {
    prepareDraftCommentInImage(event);
  }
  isAddOpen.value = true;
  toggleCommentPositionMode(false);
}

function prepareDraftCommentInPdf(event) {
  const pageContainer = event.target.closest('.page-inner-container');
  if (!pageContainer || !viewContainer) return;

  const pageLabel = pageContainer
    .closest('.vpv-page-inner-container')
    .getAttribute('aria-label');
  const pageIndex = pageLabel.charAt(pageLabel.length - 1);

  const viewRect = viewContainer.getBoundingClientRect();
  const pageRect = pageContainer.getBoundingClientRect();
  const pageScroll = viewRect.top - pageRect.top;

  const mouseTop = event.clientY;
  const y = mouseTop - viewRect.top + pageScroll;
  const x = event.clientX - pageRect.left;

  const relativeX = (x / pageRect.width) * 100;
  const relativeY = (y / pageRect.height) * 100;

  console.log(pageIndex);

  draftComment.value.position = {
    x: relativeX,
    y: relativeY,
    pageIndex: parseInt(pageIndex),
  };
}

function prepareDraftCommentInImage(event) {
  if (!viewContainer) return;

  const imageRect = viewContainer.getBoundingClientRect();

  const mouseTop = event.clientY;
  const mouseLeft = event.clientX;

  const relativeX = ((mouseLeft - imageRect.left) / imageRect.width) * 100;
  const relativeY = ((mouseTop - imageRect.top) / imageRect.height) * 100;

  draftComment.value.position = {
    x: relativeX,
    y: relativeY,
  };
}

function openComment(comment) {
  if (comment.isEditMode) return;

  openedComment.value = comment;

  if (activeTracks.value?.length === 1) {
    showCorrespondingView();
  }
}

function showCorrespondingView() {
  openedFile.value = activeTracks.value[0].files.find(
    (file) => file.uuid === openedComment.value.location.file.uuid
  );
}
</script>
