<template>
  <module
    :module="module"
    @editNote="editNote"
    @addNote="addNote"
    @bookmark="bookmark"
  />
</template>

<script>
  import Module from '@/components/modules/Module';

  import UPDATE_LAST_MODULE_MUTATION from '@/graphql/gql/mutations/updateLastModule.gql';
  import UPDATE_MODULE_BOOKMARK_MUTATION from '@/graphql/gql/mutations/updateModuleBookmark.gql';
  // import ME_QUERY from '@/graphql/gql/meQuery.gql';
  import MODULE_FRAGMENT from '@/graphql/gql/fragments/moduleParts.gql';
  import SCROLL_POSITION from '@/graphql/gql/local/scrollPosition.gql';
  import SCROLL_TO_MUTATION from '@/graphql/gql/local/mutations/scrollTo.gql';

  import meMixin from '@/mixins/me';
  import MODULE_DETAILS_QUERY from '@/graphql/gql/queries/modules/moduleDetailsQuery.gql';
  import ME_QUERY from '@/graphql/gql/queries/meQuery.gql';
  import {setModuleEditMode} from '@/graphql/cache-operations';

  export default {
    mixins: [meMixin],

    components: {
      Module,
    },

    data() {
      return {
        module: {},
        updateSent: false
      };
    },

    beforeRouteLeave(to, from, next) {
      // toggle edit mode if leavind the module subtree
      if(this.module.inEditMode && to.path.indexOf('/module/') === -1) {
        setModuleEditMode(this.module.slug, false);
      }
      next();
    },

    apollo: {
      module() {
        return {
          query: MODULE_DETAILS_QUERY,
          variables: {
            slug: this.$route.params.slug,
          },
          result({data: {module: {id}}}) {
            if (!this.updateSent) {
              this.$log.debug(`=== updating result for module ${id} ===`);
              this.updateLastVisitedModule(id);
              this.updateSent = true;
            }
          },
          fetchPolicy: 'cache-first',
        };
      },
      scrollPosition: {
        query: SCROLL_POSITION,
      },
    },

    methods: {
      updateLastVisitedModule(moduleId) {
        this.$log.debug(`updating last visited module for module ${moduleId}`);
        if (!moduleId) {
          this.$log.warn('no module id');
          return;
        }

        if (this.me.lastModule && this.me.lastModule.id === moduleId) {
          this.$log.debug('same module already set as last module');
          return;
        }

        this.$apollo.mutate({
          mutation: UPDATE_LAST_MODULE_MUTATION,
          variables: {
            input: {
              id: moduleId,
            },
          },
          update: (store, {data: {updateLastModule: {lastModule}}}) => {
            const {id, slug} = lastModule;
            this.$log.debug('updating last module', id, slug);
            const query = ME_QUERY;
            let {me} = store.readQuery({
              query,
            });
            // me.lastModule = {
            //   id,
            //   slug,
            //   __typename: 'ModuleNode',
            // };

            let edges = [...me.recentModules.edges];
            const foundIndex = edges.findIndex(edge => edge.node.slug === slug);
            if (foundIndex > -1) {
              edges = [...edges.slice(0, foundIndex), ...edges.slice(foundIndex + 1, edges.length)];
            }
            edges = [
              {
                node: lastModule,
                __typename: 'ModuleNodeEdge',
              },
              ...edges.slice(0, 2),
            ];
            const recentModules = {
              __typename: 'ModuleNodeConnection',
              edges
            };
            const data = {
              me: {
                ...me,
                recentModules,
                lastModule: {
                  ...lastModule,
                  // todo: do we really need this? shouldn't the lastModule property already include this?
                  '__typename': 'ModuleNode'
                }
              }
            };
            store.writeQuery({
              query,
              data
            });
          },

        });
      },
      bookmark(bookmarked) {
        const slug = this.module.slug;
        this.$apollo.mutate({
          mutation: UPDATE_MODULE_BOOKMARK_MUTATION,
          variables: {
            input: {
              module: slug,
              bookmarked,
            },
          },
          update: (store) => {
            const fragment = MODULE_FRAGMENT;
            const id = store.identify({
              __typename: 'ModuleNode',
              slug: slug
            });

            const module = store.readFragment({
              fragment,
              id,
            });

            let bookmark;

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

            const data = {
              ...module,
              bookmark
            };

            store.writeFragment({
              data,
              fragment,
              id,
            });
          },
          optimisticResponse: {
            __typename: 'Mutation',
            updateModuleBookmark: {
              __typename: 'UpdateModuleBookmarkPayload',
              success: true,
            },
          },
        });
      },
      addNote(id) {
        this.$store.dispatch('addNote', {
          content: id,
          parent: this.module.slug,
          type: 'module'
        });
      },
      editNote() {
        this.$store.dispatch('editNote', this.module.bookmark.note);
      },
      scrollTo() {
        if (this.scrollPosition && this.scrollPosition.scrollTo) {
          let options = {
            container: 'body',
            easing: 'ease',
            offset: -60,
            x: false,
            y: true,
          };
          setTimeout(() => {
            this.$scrollTo(`[data-scrollto="${this.scrollPosition.scrollTo}"]`, 1000, options);
            this.$apollo.mutate({
              mutation: SCROLL_TO_MUTATION,
              variables: {
                scrollTo: '',
              },
            });
          }, 250); // unfortunately this timeout is needed as it is hard to tell when everything is rendered
        }
      },
    },
  };
</script>

<style scoped lang="scss">

</style>
