import type { Command } from '@blockeditor/block-std';
import { assertExists } from '@blockeditor/global/utils';
import type { BlockModel } from '@blockeditor/store';

export const getSelectedModelsCommand: Command<
  'host',
  'selectedModels',
  {
    types?: Extract<BlockEditor.SelectionType, 'block' | 'text' | 'image'>[];
  }
> = (ctx, next) => {
  const { host } = ctx;
  assertExists(
    host,
    '`host` is required, you need to use `withHost` command before adding this command to the pipeline.'
  );

  const types = ctx.types ?? ['block', 'text', 'image'];
  const selectedModels: BlockModel[] = [];
  host.std.command
    .pipe()
    .withHost()
    .tryAll(chain => [
      chain.getTextSelection(),
      chain.getBlockSelections(),
      chain.getImageSelections(),
    ])
    .getSelectedBlocks({
      types,
    })
    .inline(ctx => {
      const { selectedBlocks } = ctx;
      assertExists(selectedBlocks);
      selectedModels.push(...selectedBlocks.map(el => el.model));
    })
    .run();

  next({ selectedModels });
};

declare global {
  namespace BlockEditor {
    interface CommandContext {
      selectedModels?: BlockModel[];
    }

    interface Commands {
      getSelectedModels: typeof getSelectedModelsCommand;
    }
  }
}
