<!--
  @component Provides the wrapped element with a popover that contains a context menu.
-->
<script lang="ts" generics="THandlerProps = undefined">
  import type {ContextMenuProviderProps} from '~/app/ui/components/hocs/context-menu-provider/props';
  import type {ContextMenuItem} from '~/app/ui/components/hocs/context-menu-provider/types';
  import Popover from '~/app/ui/generic/popover/Popover.svelte';
  import MdIcon from '~/app/ui/svelte-components/blocks/Icon/MdIcon.svelte';
  import MenuContainer from '~/app/ui/svelte-components/generic/Menu/MenuContainer.svelte';
  import MenuItem from '~/app/ui/svelte-components/generic/Menu/MenuItem.svelte';
  import MenuItemDivider from '~/app/ui/svelte-components/generic/Menu/MenuItemDivider.svelte';
  import {hasProperty} from '~/common/utils/object';

  let {
    anchorPoints = undefined,
    children,
    closeOnClickOutside = undefined,
    container = undefined,
    flip = undefined,
    items,
    offset = undefined,
    onafterclose,
    onafteropen,
    onbeforeclose,
    onbeforeopen,
    onclickitem,
    onclickoutside,
    onclicktrigger,
    popover = $bindable<Popover>(),
    reference = undefined,
    safetyGap = {left: 8, right: 8, top: 8, bottom: 8},
    snippetBefore,
    triggerBehavior = undefined,
  }: ContextMenuProviderProps<THandlerProps> = $props();

  function handleClickItem(item: ContextMenuItem<THandlerProps>): void {
    if (item.type === 'divider' || item.type === 'heading') {
      return;
    }

    onclickitem?.(item);

    if (hasProperty(item, 'handlerProps')) {
      item.handler(item.handlerProps);
    } else {
      item.handler();
    }
  }
</script>

{#if items !== undefined && items.length > 0}
  <Popover
    bind:this={popover}
    {anchorPoints}
    {closeOnClickOutside}
    {container}
    {flip}
    {offset}
    {onafterclose}
    {onafteropen}
    {onbeforeclose}
    {onbeforeopen}
    {onclickoutside}
    {onclicktrigger}
    {reference}
    {safetyGap}
    {triggerBehavior}
  >
    {#snippet snippetTrigger()}
      <div class="trigger">
        {@render children?.()}
      </div>
    {/snippet}

    {#snippet snippetPopover()}
      <div class="menu">
        <MenuContainer mode="small">
          {@const hasAnyIcon = items.some(
            (item) => item.type !== 'divider' && item.icon !== undefined,
          )}

          <div class="before">
            {#if snippetBefore}
              {@render snippetBefore()}
            {/if}
          </div>

          <!-- Key not required because all values are derived from `items`. -->
          <!-- eslint-disable-next-line svelte/require-each-key -->
          {#each items as item}
            {#if item.type === 'divider'}
              <MenuItemDivider />
            {:else if item.type === 'heading'}
              <span class="heading">
                {#if item.icon !== undefined}
                  <span class="icon">
                    <MdIcon theme={item.icon.filled === true ? 'Filled' : 'Outlined'}
                      >{item.icon.name}</MdIcon
                    >
                  </span>
                {/if}
                <span class="label">{item.text}</span>
              </span>
            {:else if item.icon !== undefined}
              <MenuItem disabled={item.disabled} onclick={() => handleClickItem(item)}>
                {#snippet snippetIcon()}
                  {#if item.icon}
                    <span class={`icon ${item.icon.color}`}>
                      <MdIcon theme={item.icon.filled === true ? 'Filled' : 'Outlined'}>
                        {item.icon.name}
                      </MdIcon>
                    </span>
                  {/if}
                {/snippet}
                <span class="label" title={item.labelOnHover}>{item.label}</span>
              </MenuItem>
            {:else}
              <MenuItem disabled={item.disabled} onclick={() => handleClickItem(item)}>
                <span class="label" title={item.labelOnHover} class:padded={hasAnyIcon}>
                  {item.label}
                </span>
              </MenuItem>
            {/if}
          {/each}
        </MenuContainer>
      </div>
    {/snippet}
  </Popover>
{:else}
  {@render children?.()}
{/if}

<style lang="scss">
  @use 'component' as *;

  .menu {
    @extend %elevation-060;

    --c-menu-container-min-width: #{rem(180px)};

    border-radius: rem(8px);

    .before {
      display: none;

      &:global(:has(> *:not(:empty))) {
        display: block;
      }
    }

    .heading {
      display: flex;
      flex-direction: row;
      align-items: center;
      justify-content: start;
      gap: var(--c-menu-item-gap, default);

      padding: var(--c-menu-item-padding, default);

      .icon {
        flex: 0 0 auto;
      }

      .label {
        flex-grow: 1 1 auto;
      }
    }

    .icon {
      display: flex;
      align-items: center;

      &.acknowledged {
        color: var(--mc-message-status-acknowledged-color);
      }

      &.declined {
        color: var(--mc-message-status-declined-color);
      }
    }

    .label {
      line-height: rem(18px);

      &.padded {
        padding-left: rem(18px + 8px);
      }
    }
  }
</style>
