<template>
  <div
    data-cy="highlight-sidebar"
    class="highlight-sidebar"
  >
    <div
      class="highlight-sidebar__close-button"
      @click="close"
    >
      <cross class="highlight-sidebar__close-icon" />
    </div>
    <div class="highlight-sidebar__section highlight-sidebar__highlight">
      <h2 class="heading-4">Meine Markierung</h2>
      <mark
        class="paragraph highlight-sidebar__highlighted-text"
        :class="[`highlight--${highlight.color}`, { 'highlight-sidebar__highlighted-text--overflow': isOverflowing }]"
        data-cy="highlight-in-sidebar"
        ref="highlightMark"
      >
        {{ highlight.text }}
      </mark>
    </div>
    <div class="highlight-sidebar__section highlight-sidebar__note">
      <h2 class="heading-4">Meine Notiz</h2>
      <div
        class="form-with-border highlight-sidebar__note-form"
        v-if="inEditMode"
      >
        <textarea
          class="borderless-textarea"
          placeholder="Notiz erfassen..."
          data-cy="highlight-note-input"
          v-model="note"
          v-auto-grow
        ></textarea>
        <a
          class="button button--primary"
          data-cy="highlight-note-save"
          @click.stop="save"
          >Speichern</a
        >
      </div>
      <div v-else>
        <!-- todo: is there any safety concern here? Should not be, as the user can only enter URLs, and also gets only
their own content to be displayed -->
        <!-- eslint-disable vue/no-v-html -->
        <p
          data-cy="highlight-note-text"
          class="highlight-sidebar__note"
          v-html="noteWithUrls"
        />
        <!-- .stop to prevent the click handler to close the sidebar (as the element won't be a child of the
            sidebar anymore once the event handler checks) -->
        <a
          class="inline-title highlight-sidebar__edit-note"
          @click.stop="enableEditMode"
          >Notiz bearbeiten</a
        >
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { HighlightNode } from '@/__generated__/graphql';
import { defineAsyncComponent, onMounted, ref } from 'vue';
export interface Props {
  highlight: HighlightNode;
}

import vAutoGrow from '@/directives/auto-grow';
import { computed } from '@vue/reactivity';

const emits = defineEmits(['close', 'update-text']);
const close = () => emits('close');

const note = ref('');

const props = defineProps<Props>();

const highlightMark = ref<HTMLElement | null>(null);

const Cross = defineAsyncComponent(() => import('@/components/icons/CrossIcon.vue'));
const inEditMode = ref(false);

onMounted(() => {
  note.value = props.highlight.note?.text || '';
  // enable edit mode if note does not yet exist from a previous save
  inEditMode.value = note.value == '';
});

const enableEditMode = () => {
  inEditMode.value = true;
};

const save = () => {
  emits('update-text', note.value);
  inEditMode.value = false;
};

const parseUrls = (text: string) => {
  /* todo: is this correct (enough)? There are more complete regex patterns to find URLs, but we're not interested in all valid
   * URLs (e.g. with protocol FTP, with an IP instead of a hostname, with usernames and ports, etc) */
  const urls = text.match(/((((https?):\/\/)|(w{3}\.))[-\w@:%_+.~#?,&//=]+)/g) || []; // taken from https://codepen.io/zuhairtaha/pen/NmbGKJ
  let parsedText = text;
  for (const url of urls) {
    parsedText = parsedText.replace(url, `<a class="text-link" target="_blank" href="${url}">${url}</a>`);
  }
  return parsedText;
};

const noteWithUrls = computed(() => {
  return parseUrls(note.value);
});

const isOverflowing = computed(() => {
  const element = highlightMark.value;
  if (element) {
    return element.scrollHeight > element.clientHeight;
  }
  return false;
});
</script>

<style scoped lang="postcss">
@import 'styles/css/mixins/desktop.css';

.highlight-sidebar {
  position: fixed;
  right: 0;
  top: 0;
  bottom: 0;
  z-index: 15;
  height: 100vh;
  background-color: var(--color-white);
  padding: var(--medium-spacing);

  box-shadow: -2px 4px 11px 0px rgba(0, 0, 0, 0.12);

  display: grid;
  grid-template-columns: 1fr 50px;
  grid-template-rows: 50px max-content;

  grid-template-areas: '. x' 'h h' 'n n';

  @mixin desktop {
    width: 300px;
  }
  &__close-button {
    grid-area: x;
  }
  &__highlight {
    grid-area: h;
  }
  &__note {
    grid-area: n;
  }

  &__section {
    border-top: 1px solid var(--color-silver);
    padding: var(--large-spacing) 0;
  }

  &__highlighted-text {
    display: inline-block;
    --num-lines: 3;
    max-height: calc(var(--regular-font-size) * var(--paragraph-line-height) * var(--num-lines));
    overflow: hidden;
    text-overflow: ellipsis;
    position: relative;
    /* white-space: nowrap; */

    &--overflow {
      &::after {
        content: '...';
        position: absolute;
        background-color: inherit;
        padding-right: 30px;
        right: 0;
        bottom: 0;
      }
    }
  }

  &__note-form {
    min-height: 100px;
  }

  &__note {
    white-space: pre-line; /* display newlines as linebreaks */
    margin-bottom: var(--medium-spacing);
  }

  &__edit-note {
    cursor: pointer;
  }
}
</style>
