import type { ItemTypes } from '@ephox/alloy';
import { Menu as BridgeMenu, type Toolbar } from '@ephox/bridge';
import { Arr, Optional, Optionals } from '@ephox/katamari';

import type { UiFactoryBackstageProviders } from 'tinymce/themes/silver/backstage/Backstage';

import { renderChoiceItem } from '../item/build/ChoiceItem';
import { renderImgItem } from '../item/build/ImageItem';
import type ItemResponse from '../item/ItemResponse';

import * as MenuUtils from './MenuUtils';
import type { SingleMenuItemSpec } from './SingleMenuTypes';

type PartialMenuSpec = MenuUtils.PartialMenuSpec;

export const createPartialChoiceMenu = (
  value: string,
  items: SingleMenuItemSpec[],
  onItemValueHandler: (itemValue: string) => void,
  columns: 'auto' | number,
  presets: Toolbar.PresetTypes,
  itemResponse: ItemResponse,
  select: (value: string) => boolean,
  providersBackstage: UiFactoryBackstageProviders
): PartialMenuSpec => {
  const hasIcons = MenuUtils.menuHasIcons(items);
  const presetItemTypes = presets !== 'color' ? 'normal' : 'color';
  const alloyItems = createChoiceItems(items, onItemValueHandler, columns, presetItemTypes, itemResponse, select, providersBackstage);
  const menuLayout: MenuUtils.MenuLayoutType = {
    menuType: presets
  };
  return MenuUtils.createPartialMenuWithAlloyItems(value, hasIcons, alloyItems, columns, menuLayout);
};

export const createChoiceItems = (
  items: SingleMenuItemSpec[],
  onItemValueHandler: (itemValue: string) => void,
  columns: 'auto' | number,
  itemPresets: Toolbar.PresetItemTypes,
  itemResponse: ItemResponse,
  select: (value: string) => boolean,
  providersBackstage: UiFactoryBackstageProviders
): ItemTypes.ItemSpec[] => Optionals.cat(
  Arr.map(items, (item) => {
    if (item.type === 'choiceitem') {
      return BridgeMenu.createChoiceMenuItem(item).fold(
        MenuUtils.handleError,
        (d) => Optional.some(renderChoiceItem(
          d,
          columns === 1,
          itemPresets,
          onItemValueHandler,
          select(d.value),
          itemResponse,
          providersBackstage,
          MenuUtils.menuHasIcons(items)
        ))
      );
    } else if (item.type === 'imageitem') {
      return BridgeMenu.createImageMenuItem(item).fold(
        MenuUtils.handleError,
        (d) => Optional.some(renderImgItem(
          d,
          onItemValueHandler,
          select(d.value),
          itemResponse,
          providersBackstage
        ))
      );
    } else if (item.type === 'resetimage') {
      return BridgeMenu.createResetImageItem(item).fold(
        MenuUtils.handleError,
        (d) => Optional.some(renderChoiceItem(
          ({
            ...d,
            type: 'choiceitem',
            text: d.tooltip,
            icon: Optional.some(d.icon),
            label: Optional.some(d.label),
          }),
          columns === 1,
          itemPresets,
          onItemValueHandler,
          select(d.value),
          itemResponse,
          providersBackstage,
          MenuUtils.menuHasIcons(items)
        ))
      );
    } else {
      return Optional.none();
    }
  })
);
