import ADD_NOTE_MUTATION from '@/graphql/gql/mutations/addNote.gql';
import CONTENT_BLOCK_QUERY from '@/graphql/gql/queries/contentBlockQuery.gql';
import CHAPTER_QUERY from '@/graphql/gql/queries/chapterQuery.gql';
import INSTRUMENT_FRAGMENT from '@/graphql/gql/fragments/instrumentParts.gql';
import MODULE_FRAGMENT from '@/graphql/gql/fragments/moduleParts.gql';
import { replaceAtIndex } from '@/graphql/immutable-operations';

const compareUuid = (note) => (element) => element.uuid === note.content;

export const constructNoteMutation = (n) => {
  let update = () => {};

  if (n.block) {
    // has a block, so it is a content block or instrument bookmark
    update = (
      store,
      {
        data: {
          addNote: { note },
        },
      }
    ) => {
      if (n.type === 'ContentBlockNode') {
        const query = CONTENT_BLOCK_QUERY;
        const variables = { id: n.block };
        const { contentBlock } = store.readQuery({
          query,
          variables,
        });

        let bookmarks;

        let index = contentBlock.bookmarks.findIndex(compareUuid(n));

        if (index > -1) {
          const el = {
            ...contentBlock.bookmarks[index],
            note,
          };
          bookmarks = [...contentBlock.bookmarks.slice(0, index), el, ...contentBlock.bookmarks.slice(index + 1)];
        } else {
          bookmarks = [...contentBlock.bookmarks];
        }

        const data = {
          contentBlock: {
            ...contentBlock,
            bookmarks,
          },
        };

        store.writeQuery({
          data,
          query,
          variables,
        });
      } else {
        const fragment = INSTRUMENT_FRAGMENT;
        const id = store.identify({
          __typename: 'InstrumentNode',
          slug: n.block,
        });
        const instrument = store.readFragment({
          fragment,
          id,
        });

        const prevBookmarks = instrument.bookmarks;
        let bookmarks;

        let index = prevBookmarks.findIndex(compareUuid(n));

        if (index > -1) {
          let el = prevBookmarks[index];
          bookmarks = replaceAtIndex(prevBookmarks, index, {
            ...el,
            note,
          });
        } else {
          bookmarks = [...prevBookmarks];
        }

        const data = {
          ...instrument,
          bookmarks,
        };

        store.writeFragment({
          data,
          fragment,
          id,
        });
      }
    };
  } else {
    // it's a chapter bookmark or a module bookmark
    update = (
      store,
      {
        data: {
          addNote: { note },
        },
      }
    ) => {
      const type = n.type === 'module' ? 'module' : 'chapter';
      const isChapter = type === 'chapter';
      let query;
      let variables;
      let fromStore;
      if (isChapter) {
        variables = { id: n.parent };
        query = CHAPTER_QUERY;
        fromStore = store.readQuery({
          query,
          variables,
        });

        const entity = fromStore[type];
        let bookmark = {
          ...entity.bookmark,
          note,
        };

        const data = {
          [type]: {
            ...entity,
            bookmark,
          },
        };

        store.writeQuery({
          data,
          query,
          variables,
        });
      } else {
        let fragment = MODULE_FRAGMENT;
        const fragmentName = 'ModuleLegacyParts';
        let id = store.identify({
          __typename: 'ModuleNode',
          slug: n.parent,
        });

        const module = store.readFragment({
          fragment,
          fragmentName,
          id,
        });
        let bookmark = {
          ...module.bookmark,
          note,
        };
        let data = {
          ...module,
          bookmark,
        };
        store.writeFragment({
          fragment,
          fragmentName,
          id,
          data,
        });
      }
    };
  }

  return {
    mutation: ADD_NOTE_MUTATION,
    variables: {
      input: {
        note: n,
      },
    },
    update,
    optimisticResponse: {
      __typename: 'Mutation',
      addNote: {
        __typename: 'AddNotePayload',
        note: {
          __typename: 'NoteNode',
          id: -1,
          text: n.text,
        },
      },
    },
  };
};
