<template>
  <div
    :class="{'hideable-element--hidden': hidden}"
    class="content-block__container hideable-element">
    <div
      :class="specialClass"
      class="content-block">
      <div
        class="block-actions"
        v-if="canEditContentBlock && editModule">
        <user-widget
          :show-menu="false"
          v-bind="me"
          class="block-actions__user-widget content-block__user-widget"/>
        <more-options-widget>
          <li class="popover-links__link"><a @click="deleteContentBlock(contentBlock)">Löschen</a></li>
          <li class="popover-links__link"><a @click="editContentBlock(contentBlock)">Bearbeiten</a></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/chapterQuery.gql';
  import DELETE_CONTENT_BLOCK_MUTATION from '@/graphql/gql/mutations/deleteContentBlock.gql';

  import {meQuery} from '@/graphql/queries';

  import {mapGetters} from 'vuex';

  import {isHidden} from '@/helpers/content-block';

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

  };

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

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

    data() {
      return {
        showVisibility: false,
        me: {}
      }
    },

    computed: {
      ...mapGetters(['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)
        });
      },
      schoolClass() {
        return this.me.selectedClass;
      },
      hidden() {
        return isHidden(this.contentBlock, this.schoolClass);
      },
      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.edges.splice(data.chapter.contentBlocks.edges.findIndex(edge => edge.node.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)];
      }
    },

    apollo: {
      me: meQuery
    }
  }
</script>

<style scoped lang="scss">
  @import "@/styles/_variables.scss";
  @import "@/styles/_mixins.scss";

  .content-block {
    margin-bottom: 2.5em;
    position: relative;

    &__container {
      position: relative;
    }

    &__title {
      line-height: 1.5;
    }

    &__instrument-label {
      margin-bottom: 0;
      @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;
        @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>
