import { Ctx } from '../ctx/base';
import {
  isArray,
  isNullish,
  isNumber,
  isPlacement,
  isRecord,
  isString,
} from '../guardUtils.js';
import { IconWithEmoji, isIconWithEmoji } from '../icon';

export type ContentAreaSidebarItemsHook = {
  /**
   * Use this function to declare new items in the content area sidebar
   *
   * @tag sidebarItems
   */
  contentAreaSidebarItems: (
    ctx: ContentAreaSidebarItemsCtx,
  ) => ContentAreaSidebarItem[];
};

export type ContentAreaSidebarItemsCtx = Ctx;

/**
 * An object expressing an item in the content area sidebar
 *
 * @see {isContentAreaSidebarItem}
 */
export type ContentAreaSidebarItem = {
  /** Label to be shown. Must be unique. */
  label: string;
  /**
   * Icon to be shown alongside the label. Can be a FontAwesome icon name (ie.
   * `"address-book"`), a custom SVG definition, or an emoji. To maintain visual
   * consistency with the rest of the interface, try to use FontAwesome icons
   * whenever possible.
   */
  icon: IconWithEmoji;
  /** ID of the page linked to the item */
  pointsTo: {
    pageId: string;
  };
  /**
   * Expresses where you want the item to be placed inside the sidebar. If not
   * specified, the item will be placed after the standard items provided by
   * DatoCMS itself.
   */
  placement?: ['before' | 'after', 'menuItems' | 'seoPreferences'];
  /**
   * If different plugins specify the same `placement` for their panels, they
   * will be displayed by ascending `rank`. If you want to specify an explicit
   * value for `rank`, make sure to offer a way for final users to customize it
   * inside the plugin's settings form, otherwise the hardcoded value you choose
   * might clash with the one of another plugin!
   */
  rank?: number;
};

export function isContentAreaSidebarItem(
  value: unknown,
): value is ContentAreaSidebarItem {
  return (
    isRecord(value) &&
    isString(value.label) &&
    isIconWithEmoji(value.icon) &&
    isRecord(value.pointsTo) &&
    isString(value.pointsTo.pageId) &&
    (isNullish(value.placement) || isPlacement(value.placement)) &&
    (isNullish(value.rank) || isNumber(value.rank))
  );
}

export function isReturnTypeOfContentAreaSidebarItemsHook(
  value: unknown,
): value is ContentAreaSidebarItem[] {
  return isArray(value, isContentAreaSidebarItem);
}
