<script>
import theme from "#build/b24ui/editor-toolbar";
</script>

<script setup>
import { computed, inject } from "vue";
import { Primitive, Separator } from "reka-ui";
import { defu } from "defu";
import { BubbleMenu, FloatingMenu } from "@tiptap/vue-3/menus";
import { reactiveOmit } from "@vueuse/core";
import { useAppConfig } from "#imports";
import { useComponentProps } from "../composables/useComponentProps";
import { useForwardProps } from "../composables/useForwardProps";
import { isArrayOfArray, pick, omit } from "../utils";
import { createHandlers } from "../utils/editor";
import { tv } from "../utils/tv";
import B24Button from "./Button.vue";
import B24DropdownMenu from "./DropdownMenu.vue";
import B24Tooltip from "./Tooltip.vue";
defineOptions({ inheritAttrs: false });
const _props = defineProps({
  as: { type: null, required: false },
  color: { type: null, required: false, default: "air-tertiary-no-accent" },
  activeColor: { type: null, required: false, default: "air-tertiary-accent" },
  size: { type: null, required: false, default: "sm" },
  items: { type: null, required: false },
  editor: { type: Object, required: true },
  class: { type: null, required: false },
  b24ui: { type: Object, required: false },
  layout: { type: String, required: false, default: "fixed" },
  pluginKey: { type: [Object, String], required: false },
  updateDelay: { type: Number, required: false },
  resizeDelay: { type: Number, required: false },
  shouldShow: { type: [Function, null], required: false },
  appendTo: { type: Function, required: false, skipCheck: true },
  getReferencedVirtualElement: { type: Function, required: false },
  options: { type: Object, required: false }
});
defineSlots();
const props = useComponentProps("editorToolbar", _props);
const appConfig = useAppConfig();
const handlers = inject("editorHandlers", computed(() => createHandlers()));
const Component = computed(() => {
  return {
    bubble: BubbleMenu,
    floating: FloatingMenu,
    fixed: "template"
  }[props.layout];
});
const rootProps = useForwardProps(reactiveOmit(props, "as", "color", "activeColor", "size", "items", "layout", "editor", "class", "b24ui"));
const options = computed(() => defu(props.options, {
  offset: 8,
  shift: { padding: 8 }
}));
const b24ui = computed(() => tv({ extend: theme, ...appConfig.b24ui?.editorToolbar || {} })({
  layout: props.layout
}));
const groups = computed(
  () => props.items?.length ? isArrayOfArray(props.items) ? props.items : [props.items] : []
);
function isActive(item) {
  if (!props.editor?.isEditable) {
    return false;
  }
  if ("items" in item && item.items?.length) {
    return item.items?.some((item2) => isActive(item2)) || false;
  }
  if (!("kind" in item)) {
    return item.active ?? false;
  }
  const handler = handlers?.value?.[item.kind];
  return handler?.isActive(props.editor, item) || false;
}
function isDisabled(item) {
  if (!props.editor?.isEditable) {
    return true;
  }
  if ("items" in item && item.items?.length) {
    const items = isArrayOfArray(item.items) ? item.items.flat() : item.items;
    const actionableItems = items.filter((item2) => item2.type !== "separator" && item2.type !== "label");
    if (actionableItems.length === 0) {
      return true;
    }
    return actionableItems.every((item2) => isDisabled(item2));
  }
  if (!("kind" in item)) {
    return item.disabled ?? false;
  }
  const handler = handlers?.value?.[item.kind];
  if (!handler) {
    return false;
  }
  if (handler.isDisabled?.(props.editor, item)) {
    return true;
  }
  return !handler.canExecute(props.editor, item);
}
function onClick(e, item) {
  if (!props.editor?.isEditable || isDisabled(item)) {
    return;
  }
  if ("items" in item || !("kind" in item)) {
    if ("onClick" in item) {
      for (const onClick2 of Array.isArray(item.onClick) ? item.onClick : [item.onClick]) {
        onClick2?.(e);
      }
    }
    return;
  }
  const handler = handlers?.value?.[item.kind];
  if (handler) {
    handler.execute(props.editor, item).run();
  }
}
function getActiveChildItem(item) {
  if (!item.items) {
    return void 0;
  }
  const items = isArrayOfArray(item.items) ? item.items.flat() : item.items;
  return items.find((childItem) => {
    if (!("kind" in childItem)) {
      return false;
    }
    return isActive(childItem);
  });
}
function getButtonProps(item) {
  const baseProps = omit(item, ["kind", "mark", "align", "level", "href", "src", "pos", "items", "slot", "checkedIcon", "loadingIcon", "externalIcon", "content", "arrow", "portal", "modal", "tooltip", "onClick"]);
  if ("items" in item && item.items?.length) {
    const activeChild = getActiveChildItem(item);
    if (activeChild?.icon) {
      baseProps.icon = activeChild.icon;
    }
    if (activeChild?.label && baseProps.label !== void 0) {
      baseProps.label = activeChild.label;
    }
  }
  return defu(baseProps, {
    color: props.color,
    activeColor: props.activeColor,
    size: props.size
  });
}
function getDropdownProps(item) {
  const baseProps = pick(item, ["size", "checkedIcon", "loadingIcon", "externalIcon", "content", "arrow", "portal", "modal", "b24ui"]);
  return defu(baseProps, {
    modal: false,
    size: props.size
  });
}
function mapDropdownItem(item) {
  const children = "children" in item && Array.isArray(item.children) ? item.children.map(mapDropdownItem) : void 0;
  if (!("kind" in item)) {
    return children ? { ...item, children } : item;
  }
  const editorToolbarItem = item;
  return {
    ...editorToolbarItem,
    ...children && { children },
    // @ts-expect-error: need test at nuxt.ui? but this work
    active: isActive(editorToolbarItem),
    // @ts-expect-error: need test at nuxt.ui? but this work
    disabled: isDisabled(editorToolbarItem),
    // @ts-expect-error: need test at nuxt.ui? but this work
    onSelect: (e) => onClick(e, editorToolbarItem)
  };
}
function getDropdownItems(item) {
  if (!item.items) {
    return [];
  }
  return isArrayOfArray(item.items) ? item.items.map((group) => group.map(mapDropdownItem)) : [item.items.map(mapDropdownItem)];
}
</script>

<template>
  <Primitive
    :as="Component"
    v-bind="Component !== 'template' ? {
  editor: props.editor,
  tabindex: -1,
  class: b24ui.root({ class: props.b24ui?.root }),
  ...rootProps,
  options,
  ...$attrs
} : {
  ...$attrs
}"
  >
    <Primitive :as="props.as" role="toolbar" data-slot="base" :class="b24ui.base({ class: [props.b24ui?.base, props.class] })">
      <template v-for="(group, groupIndex) in groups" :key="`group-${groupIndex}`">
        <div role="group" data-slot="group" :class="b24ui.group({ class: props.b24ui?.group })">
          <template v-for="(item, index) in group" :key="`group-${groupIndex}-${index}`">
            <slot
              :name="item.slot || 'item'"
              :item="item"
              :index="index"
              :is-active="isActive"
              :is-disabled="isDisabled"
              :on-click="onClick"
            >
              <B24DropdownMenu
                v-if="'items' in item && item.items?.length"
                v-bind="getDropdownProps(item)"
                :items="getDropdownItems(item)"
              >
                <B24Tooltip v-if="item.tooltip" :disabled="isDisabled(item)" v-bind="{ ...item.tooltip || {} }">
                  <B24Button :active="isActive(item)" :disabled="isDisabled(item)" v-bind="getButtonProps(item)" @click="onClick($event, item)" />
                </B24Tooltip>

                <B24Button v-else :active="isActive(item)" :disabled="isDisabled(item)" v-bind="getButtonProps(item)" @click="onClick($event, item)" />
              </B24DropdownMenu>

              <B24Tooltip v-else-if="item.tooltip" :disabled="isDisabled(item)" v-bind="{ ...item.tooltip || {} }">
                <B24Button
                  :active="isActive(item)"
                  :disabled="isDisabled(item)"
                  v-bind="getButtonProps(item)"
                  :b24ui="item.b24ui"
                  @click="onClick($event, item)"
                />
              </B24Tooltip>

              <B24Button
                v-else
                :active="isActive(item)"
                :disabled="isDisabled(item)"
                v-bind="getButtonProps(item)"
                :b24ui="item.b24ui"
                @click="onClick($event, item)"
              />
            </slot>
          </template>
        </div>

        <Separator
          v-if="groupIndex < groups.length - 1"
          data-slot="separator"
          :class="b24ui.separator({ class: props.b24ui?.separator })"
          orientation="vertical"
        />
      </template>
    </Primitive>
  </Primitive>
</template>
