import * as _ from "lodash";
import React from "react";

export enum CommandLineModes {
  COMMAND = "COMMAND",
  OPTION = "OPTION",
  PROMPT = "PROMPT",
}

export enum ProwessCommands {
  CREATE_FRAME = "CREATE_FRAME",
  GOTO_FRAME = "GOTO_FRAME",
  SEARCH = "SEARCH",
}

export enum CommandPriority {
  LOW = 1,
  MEDIUM = 2,
  HIGH = 3,
}

export enum CommandLineSource {
  CANVAS = "CANVAS",
}

export interface Command {
  id: string; // unique identifier...
  title: string;
  shortcut?: string;
  source: string; // place where the command is added, makes for easy reset
  priority: number; // highest priority commands displayed first
  type?: string; // whether it's a command... or an option, can be used for filtering
  onSelect: () => void;
  onCancel?: () => void;
  externalSearch?: (search: string) => void;
}

export type CommandLineContext = {
  commands: Command[];
  isVisible: boolean;
  isLoading: boolean;
  prompt: string;
  mode: CommandLineModes;
  setIsLoading: (val: boolean) => void;
  setCommands: (commands: Command[]) => void;
  addCommands: (commands: Command[]) => void;
  addOptions: (commands: Command[]) => void;
  clearCommandsFromSource: (source: string) => void;
  setPrompt: (val: string) => void;
  setMode: (mode: CommandLineModes) => void;
  toggle: () => void;
  reset: () => void;
  setIsVisible: (val: boolean) => void;
  promptCallback: (prompt: string) => void;
  setPromptCallback: (callback: any) => void;
  placeholder: string;
  setPlaceholder: (placeholder: string) => void;
};

export const CommandLineContext = React.createContext<CommandLineContext>({
  commands: [],
  isVisible: false,
  isLoading: false,
  prompt: "",
  mode: CommandLineModes.COMMAND,
  // functions will be replaced & implemented below
  toggle: _.noop,
  setCommands: _.noop,
  addCommands: _.noop,
  setIsLoading: _.noop,
  setPrompt: _.noop,
  reset: _.noop,
  clearCommandsFromSource: _.noop,
  setMode: _.noop,
  addOptions: _.noop,
  setIsVisible: _.noop,
  promptCallback: _.noop,
  setPromptCallback: _.noop,
  placeholder: "",
  setPlaceholder: _.noop,
});

function CommandLineProvider(props: { children: any }) {
  const [isVisible, setIsVisible] = React.useState(false);
  const [commands, setCommands] = React.useState<Command[]>([]);
  const [isLoading, setIsLoading] = React.useState(false);
  const [prompt, setPrompt] = React.useState("Prowess Command");
  const [placeholder, setPlaceholder] = React.useState<string>(
    "Start typing..."
  );
  const [mode, setMode] = React.useState<CommandLineModes>(
    CommandLineModes.COMMAND
  );
  const [promptCallback, setPromptCallback] = React.useState<any>(
    (prompt: string) => {}
  );

  return (
    <CommandLineContext.Provider
      // set state values her
      value={{
        commands,
        setCommands,
        isVisible,
        isLoading,
        prompt,
        mode,
        setMode,
        setIsVisible,
        toggle: () => {
          setIsVisible((prev) => !prev);
        },
        setIsLoading: (val: boolean) => {
          setIsLoading(val);
        },
        setPrompt,
        reset: () => {
          setCommands([]);
          setIsVisible(false);
        },
        addCommands: (commands: Command[]) => {
          setCommands((prev) => [...prev, ...commands]);
        },
        clearCommandsFromSource: (source: string) => {
          setCommands((prev) => prev.filter((prev) => prev.source !== source));
        },
        addOptions: (commands: Command[]) => {
          // remove all previous options (ephemeral) then add new ones
          setCommands((prev) => [
            ...prev.filter((prev) => prev.type !== "OPTION"),
            ...commands,
          ]);
        },
        promptCallback,
        setPromptCallback,
        placeholder,
        setPlaceholder,
      }}
    >
      {props.children}
    </CommandLineContext.Provider>
  );
}

export const useCommandLineContext = () => React.useContext(CommandLineContext);

export default CommandLineProvider;
