<template>
  <div
    :class="{'hideable-element--greyed-out': hidden}"
    class="content-block__container hideable-element">
    <div
      :class="specialClass"
      class="content-block">
      <div
        class="block-actions"
        v-if="canEditContentBlock && editModule">
        <user-widget
          v-bind="me"
          class="block-actions__user-widget content-block__user-widget"/>
        <more-options-widget>
          <li class="popover-links__link">
            <popover-link
              data-cy="delete-content-block-link"
              text="Löschen"
              @link-action="deleteContentBlock(contentBlock)" />

          </li>

          <li class="popover-links__link">
            <popover-link
              text="Bearbeiten"
              @link-action="editContentBlock(contentBlock)" />
          </li>
        </more-options-widget>
      </div>
      <div class="content-block__visibility">
        <visibility-action
          :block="contentBlock"
          v-if="canEditModule"/>
      </div>

      <h3
        class="content-block__instrument-label"
        v-if="instrumentLabel !== ''">{{ instrumentLabel }}</h3>
      <h4
        class="content-block__title"
        v-if="!contentBlock.indent">{{ contentBlock.title }}</h4>

      <content-component
        :key="component.id"
        :component="component"
        :root="root"
        :parent="contentBlock"
        :bookmarks="contentBlock.bookmarks"
        :notes="contentBlock.notes"
        v-for="component in contentBlocksWithContentLists.contents"
      />

    </div>

    <add-content-button
      :after="contentBlock"
      v-if="canEditModule"/>

  </div>

</template>

<script>
  import AddContentButton from '@/components/AddContentButton';
  import MoreOptionsWidget from '@/components/MoreOptionsWidget';
  import UserWidget from '@/components/UserWidget';
  import VisibilityAction from '@/components/visibility/VisibilityAction';
  import ContentComponent from '@/components/content-blocks/ContentComponent';

  import CHAPTER_QUERY from '@/graphql/gql/queries/chapterQuery.gql';
  import DELETE_CONTENT_BLOCK_MUTATION from '@/graphql/gql/mutations/deleteContentBlock.gql';

  import {mapState} from 'vuex';

  import me from '@/mixins/me';
  import {hidden} from '@/helpers/visibility';
  import {CONTENT_TYPE} from '@/consts/types';
  import PopoverLink from '@/components/ui/PopoverLink';

  const instruments = {
    base_communication: 'Sprache & Kommunikation',
    base_society: 'Gesellschaft',
    base_interdisciplinary: 'Überfachliches Instrument',

  };

  export default {
    name: 'ContentBlock',
    props: ['contentBlock', 'parent'],

    mixins: [me],

    components: {
      PopoverLink,
      ContentComponent,
      AddContentButton,
      VisibilityAction,
      MoreOptionsWidget,
      UserWidget
    },

    computed: {
      ...mapState(['editModule']),
      canEditModule() {
        return !this.contentBlock.indent && this.editModule;
      },
      specialClass() {
        return `content-block--${this.contentBlock.type.toLowerCase()}`;
      },
      instrumentLabel() {
        const contentType = this.contentBlock.type.toLowerCase();
        if (!(contentType in instruments)) {
          return '';
        }

        return `Instrument - ${instruments[contentType]}`;
      },
      canEditContentBlock() {
        return this.contentBlock.mine && !this.contentBlock.indent;
      },
      contentBlocksWithContentLists() {
        /*
        collects all content_list_items in content_lists:
        {
          text_block,
          content_list_item: [contents...],
          content_list_item: [contents...],
          text_block
        } becomes
        {
          text_block,
          content_list: [content_list_item: [contents...], content_list_item: [contents...]],
          text_block
        }
        if there's only a single content_list_item it should not be displayed as list like so
        {
          text_block,
          content_list_item: [text_block, image_block],
        } becomes
        {
          text_block,
          text_block,
          image_block
        }
        */
        let contentList = [];
        let startingIndex = 0;
        let newContent = this.contentBlock.contents.reduce((newContents, content, index) => {
          // collect content_list_items
          if (content.type === 'content_list_item') {
            contentList = [...contentList, content];
            if (index === this.contentBlock.contents.length - 1) { // content is last element of contents array
              let updatedContent = [...newContents, ...this.createContentListOrBlocks(contentList, startingIndex)];
              startingIndex = this.updateStartingIndex(startingIndex, contentList);
              return updatedContent;
            }
            return newContents;
          } else {
            // handle all other items and reset current content_list if necessary
            if (contentList.length !== 0) {
              newContents = [...newContents, ...this.createContentListOrBlocks(contentList, startingIndex), content];
              startingIndex = this.updateStartingIndex(startingIndex, contentList);
              contentList = [];
              return newContents;
            } else {
              return [...newContents, content];
            }
          }
        }, []);
        return Object.assign({}, this.contentBlock, {
          contents: this.removeSingleContentListItem(newContent, startingIndex)
        });
      },
      hidden() {
        return hidden({
          block: this.contentBlock,
          schoolClass: this.schoolClass,
          type: CONTENT_TYPE
        });
      },
      root() {
        // we need the root content block id, not the generated content block if inside a content list block
        return this.contentBlock.root ? this.contentBlock.root : this.contentBlock.id;
      }
    },
    methods: {
      editContentBlock(contentBlock) {
        this.$store.dispatch('editContentBlock', contentBlock.id);
      },
      deleteContentBlock(contentBlock) {
        const parent = this.parent;
        const id = contentBlock.id;
        this.$apollo.mutate({
          mutation: DELETE_CONTENT_BLOCK_MUTATION,
          variables: {
            input: {
              id
            }
          },
          update(store, {data: {deleteContentBlock: {success}}}) {
            try {
              if (success) {
                const query = CHAPTER_QUERY;
                const variables = {
                  id: parent
                };
                const data = store.readQuery({query, variables});
                data.chapter.contentBlocks.splice(data.chapter.contentBlocks.findIndex(contentBlock => contentBlock.id === id), 1);
                store.writeQuery({query, variables, data});
              }
            } catch (e) {
              // Query did not exist in the cache, and apollo throws a generic Error. Do nothing
            }
          }
        });
      },
      createContentListOrBlocks(contentList, startingIndex) {
        return [{
          type: 'content_list',
          contents: contentList,
          id: contentList[0].id,
          startingIndex
        }];
      },
      updateStartingIndex(startingIndex, contentList) {
        return contentList.length > 0 ? startingIndex + contentList.length : startingIndex;
      },
      removeSingleContentListItem(content, index) {
        // just handle the case where we have one contentlistItem ( no index like "a)"" will be shown)

        if (index === 0) {
          return content;
        }

        const contentLists = content.filter(contentItem => contentItem.type === 'content_list');
        if (contentLists.length !== 1) {
          return content;
        }

        const listIndex = content.findIndex(contentItem => contentItem.type === 'content_list');
        if (content[listIndex].contents.length !== 1) {
          return content;
        }
        return [...content.slice(0, listIndex), ...content[listIndex].contents[0].value, ...content.slice(listIndex + 1)];
      }
    }
  };
</script>

<style scoped lang="scss">
  @import "~styles/helpers";

  .content-block {
    margin-bottom: $section-spacing;
    position: relative;

    &__container {
      position: relative;
    }

    &__title {
      line-height: 1.5;
      margin-top: -0.5rem; // to offset the 1.5 line height, it leaves a padding on top
    }

    &__instrument-label {
      margin-bottom: $medium-spacing;
      @include regular-text();
    }

    &__action-button {
      cursor: pointer;
    }

    &__user-widget {
      margin-right: 0;
    }

    &--base_communication {
      @include content-box($color-accent-1-list);

      .content-block__instrument-label {
        color: $color-accent-1-dark;
      }
    }

    &--task {
      @include light-border(bottom);

      .content-block__title {
        color: $color-brand;
        margin-top: $default-padding;
        margin-bottom: $large-spacing;
        @include light-border(bottom);

        @include desktop {
          margin-top: 0;
        }
      }
    }

    &--base_society {
      @include content-box($color-accent-2-list);

      .content-block__instrument-label {
        color: $color-accent-2-dark;
      }
    }

    &--base_interdisciplinary {
      @include content-box($color-accent-4-list);

      .content-block__instrument-label {
        color: $color-accent-4-dark;
      }
    }

    /deep/ p {
      line-height: 1.5;
      margin-bottom: 1em;

      &:last-child {
        margin-bottom: 0;
      }
    }

    /deep/ .text-block {
      ul {
        padding-left: 25px;
      }

      li {
        list-style: disc;
        line-height: 1.5;
      }
    }

  }
</style>
