import { Block } from "components/Blocks/Block";
import { create } from "zustand";
import { combine, createJSONStorage, persist } from "zustand/middleware";

type SelectedBlock = Pick<Block, "value" | "parent">;

export type EditorIframePage = { type: "iframe"; url: string };
export type EditorOpenPage = string | EditorIframePage;

export const getEditorPageKey = (page: EditorOpenPage): string =>
  typeof page === "string" ? page : `iframe:${page.url}`;

export const useUIState = create(
  combine(
    {
      lastUsedHighlight: "1" as "1" | "2" | "3",
      focusedEntity: null as
        | { entityType: "page"; entityID: string }
        | { entityType: "block"; entityID: string; parent: string }
        | { entityType: "footnote"; entityID: string; parent: string }
        | null,
      foldedBlocks: [] as string[],
      openPages: [] as EditorOpenPage[],
      selectedBlocks: [] as SelectedBlock[],
      openPopover: null as string | null,
    },
    (set) => ({
      setOpenPopover: (id: string | null) => {
        set({ openPopover: id });
      },
      toggleFold: (entityID: string) => {
        set((state) => {
          return {
            foldedBlocks: state.foldedBlocks.includes(entityID)
              ? state.foldedBlocks.filter((b) => b !== entityID)
              : [...state.foldedBlocks, entityID],
          };
        });
      },
      openPage: (parent: EditorOpenPage, page: EditorOpenPage) =>
        set((state) => {
          let parentKey = getEditorPageKey(parent);
          let parentPosition = state.openPages.findIndex(
            (s) => getEditorPageKey(s) === parentKey,
          );
          return {
            openPages:
              parentPosition === -1
                ? [page]
                : [...state.openPages.slice(0, parentPosition + 1), page],
          };
        }),
      closePage: (pages: EditorOpenPage | EditorOpenPage[]) =>
        set((s) => {
          let keys = [pages].flat().map(getEditorPageKey);
          return {
            openPages: s.openPages.filter(
              (c) => !keys.includes(getEditorPageKey(c)),
            ),
          };
        }),
      setFocusedBlock: (
        b:
          | { entityType: "page"; entityID: string }
          | { entityType: "block"; entityID: string; parent: string }
          | { entityType: "footnote"; entityID: string; parent: string }
          | null,
      ) => set(() => ({ focusedEntity: b })),
      setSelectedBlock: (block: SelectedBlock) =>
        set((state) => {
          return { ...state, selectedBlocks: [block] };
        }),
      setSelectedBlocks: (blocks: SelectedBlock[]) =>
        set((state) => {
          return { ...state, selectedBlocks: blocks };
        }),
      addBlockToSelection: (block: SelectedBlock) =>
        set((state) => {
          if (state.selectedBlocks.find((b) => b.value === block.value))
            return state;
          return { ...state, selectedBlocks: [...state.selectedBlocks, block] };
        }),
      removeBlockFromSelection: (block: { value: string }) =>
        set((state) => {
          return {
            ...state,
            selectedBlocks: state.selectedBlocks.filter(
              (f) => f.value !== block.value,
            ),
          };
        }),
    }),
  ),
);
