import { fsm2 } from "@heydovetail/ui-components";
import memoizeOne from "memoize-one";
import { Plugin, EditorState } from "prosemirror-state";
import { Decoration, DecorationSet } from "prosemirror-view";
import { style } from "typestyle-react";
import { PluginDescriptor } from "../util/PluginDescriptor";

export interface PluginState {
  type: "default";

  /**
   * The color of the selection.
   */
  color: string;
}

export const transition = fsm2.createTransition<PluginState>()({
  default: {
    withColor: ({ type }, { color }: { color: string }) => ({
      type,
      color
    })
  }
});

const { key, getPluginState, setPluginState, getPluginStateOrThrow } = new PluginDescriptor<PluginState>("BlurSelectionPlugin");
export { setPluginState };

/**
 * A plugin that renders the visualises the editor selection when the editor is
 * blurred.
 */
export class BlurSelectionPlugin extends Plugin {
  constructor({ color, skip }: { color: string, skip: (editor: EditorState) => boolean}) {
    const getClassName = memoizeOne((color: string) =>
      style({
        $nest: {
          ".ProseMirror:not(.ProseMirror-focused) &": {
            backgroundColor: color,
            padding: "5px 0"
          }
        }
      })
    );

    super({
      key: key,

      state: {
        init(): PluginState {
          return { type: "default", color: color };
        },
        apply(tr, cur: PluginState): PluginState {
          const nextPluginState = getPluginState(tr);
          return nextPluginState !== null ? nextPluginState : cur;
        }
      },

      props: {
        decorations(state) {
          return skip(state) || state.selection.empty
            ? null
            : DecorationSet.create(state.doc, [
                Decoration.inline(state.selection.from, state.selection.to, {
                  class: getClassName(getPluginStateOrThrow(state).color)
                })
              ]);
        }
      }
    });
  }
}
