<template>
  <div
    :data-scrollto="chapter.id"
    class="chapter"
    data-cy="chapter"
    ref="wrapper"
  >
    <div
      :class="{ 'hideable-element--greyed-out': titleGreyedOut }"
      class="hideable-element"
      v-if="!titleHidden"
    >
      <h3
        class="chapter__title"
        :id="'chapter-' + index"
      >
        {{ chapter.title }}
        <copy-link :id="chapter.id" />
      </h3>
    </div>

    <visibility-action
      :block="chapter"
      type="chapter-title"
      v-if="editMode"
    />

    <bookmark-actions
      :bookmarked="!!chapter.bookmark"
      :note="note"
      :edit-mode="editMode"
      class="chapter__bookmark-actions"
      data-cy="chapter-bookmark-actions"
      @add-note="addNote"
      @edit-note="editNote"
      @bookmark="bookmark()"
    />
    <div
      :class="{ 'hideable-element--greyed-out': descriptionGreyedOut }"
      class="chapter__intro intro hideable-element"
      v-if="!descriptionHidden"
    >
      <visibility-action
        :block="chapter"
        :chapter="true"
        type="chapter-description"
        v-if="editMode"
      />
      <p class="chapter__description">
        {{ chapter.description }}
      </p>
    </div>

    <add-content-button
      :where="{ parent: chapter }"
      v-if="editMode"
    />

    <content-block
      :content-block="contentBlock"
      :parent="chapter"
      :edit-mode="editMode"
      v-for="contentBlock in filteredContentBlocks"
      :key="contentBlock.id"
    />
  </div>
</template>

<script setup lang="ts">
import { computed, onMounted, ref } from 'vue';
import ContentBlock from '@/components/ContentBlock.vue';
import AddContentButton from '@/components/AddContentButton.vue';
import BookmarkActions from '@/components/notes/BookmarkActions.vue';
import VisibilityAction from '@/components/visibility/VisibilityAction.vue';
import CopyLink from '@/components/CopyLink.vue';
import type { Chapter } from '@/@types';
import { hidden } from '@/helpers/visibility';
import { CHAPTER_DESCRIPTION_TYPE, CHAPTER_TITLE_TYPE, CONTENT_TYPE } from '@/consts/types';
import { useStore } from 'vuex';

import UPDATE_CHAPTER_BOOKMARK_MUTATION from '@/graphql/gql/mutations/updateChapterBookmark.gql';
import CHAPTER_QUERY from '@/graphql/gql/queries/chapterQuery.gql';
import { getMe } from '@/mixins/me';
import { useMutation } from '@vue/apollo-composable';
import { useRoute } from 'vue-router';
import { PAGE_LOAD_TIMEOUT } from '@/consts/navigation.consts';

export interface Props {
  chapter: Chapter;
  index: number;
  editMode: boolean;
}

const { schoolClass } = getMe();

const store = useStore();
const route = useRoute();
const wrapper = ref<HTMLElement | null>(null);

onMounted(() => {
  const element = wrapper.value;
  if (element !== null) {
    if (route.hash === `#${props.chapter.id}`) {
      setTimeout(() => {
        const rect = element.getBoundingClientRect();
        window.scrollTo({ top: rect.y, behavior: 'smooth' });
      }, PAGE_LOAD_TIMEOUT);
    }
  }
});

const props = withDefaults(defineProps<Props>(), {
  index: 0,
  editMode: false,
});

const filteredContentBlocks = computed(() => {
  if (!(props.chapter && props.chapter.contentBlocks)) {
    return [];
  }
  if (props.editMode) {
    return props.chapter.contentBlocks;
  }
  return props.chapter.contentBlocks.filter(
    (contentBlock) =>
      !hidden({
        block: contentBlock,
        schoolClass: schoolClass.value,
        type: CONTENT_TYPE,
      })
  );
});
const note = computed(() => {
  if (props.chapter && props.chapter.bookmark) {
    return props.chapter.bookmark.note;
  }
  return false;
});
const titleGreyedOut = computed(() => {
  return textHidden(CHAPTER_TITLE_TYPE) && props.editMode;
});
const titleHidden = computed(() => {
  // never hidden when editing the module
  if (props.chapter.titleHidden === true) {
    return true;
  }
  return textHidden(CHAPTER_TITLE_TYPE) && !props.editMode;
});
const descriptionGreyedOut = computed(() => {
  return textHidden(CHAPTER_DESCRIPTION_TYPE) && props.editMode;
});
const descriptionHidden = computed(() => {
  // never hidden when editing the module
  if (props.chapter.descriptionHidden === true) {
    return true;
  }
  return textHidden(CHAPTER_DESCRIPTION_TYPE) && !props.editMode;
});

const { mutate: bookmark } = useMutation(UPDATE_CHAPTER_BOOKMARK_MUTATION, () => {
  const bookmarked = !props.chapter.bookmark;
  const id = props.chapter.id;
  return {
    variables: {
      input: {
        chapter: id,
        bookmarked,
      },
    },
    update: (store: any) => {
      const query = CHAPTER_QUERY;
      const variables = { id };
      const { chapter } = store.readQuery({
        query,
        variables,
      });

      let bookmark;

      if (bookmarked) {
        bookmark = {
          __typename: 'ChapterBookmarkNode',
          note: null,
        };
      } else {
        bookmark = null;
      }

      const data = {
        chapter: {
          ...chapter,
          bookmark,
        },
      };

      store.writeQuery({
        data,
        query,
        variables,
      });
    },

    optimisticResponse: {
      __typename: 'Mutation',
      updateChapterBookmark: {
        __typename: 'UpdateChapterBookmarkPayload',
        success: true,
      },
    },
  };
});

const addNote = (id: string) => {
  store.dispatch('addNote', {
    content: id,
    parent: props.chapter.id,
  });
};
const editNote = () => {
  store.dispatch('editNote', props.chapter.bookmark.note);
};
const textHidden = (type: string) => {
  return hidden({
    block: props.chapter,
    schoolClass: schoolClass.value,
    type,
  });
};
</script>

<script></script>

<style lang="scss">
/* todo: re-add `scoped`, same as in ContentBlock.vue  */
@import 'styles/helpers';

.chapter {
  position: relative;

  &__bookmark-actions {
    margin-top: 3px;
  }

  &__intro {
    position: relative;
  }

  &__title {
    display: flex;
    justify-content: space-between;
    align-items: center;
  }

  &__description {
    @include lead-paragraph;

    margin-bottom: $large-spacing;
  }
}
</style>
