// Nav -- a navigation link list, flat or with submenus.
//
//   <Nav items='[{"label":"Home","href":"/","value":"home"}]' active="home" />
//
// An item carrying its own items array becomes a submenu. Depth is capped at
// three levels: this template language has no component recursion, so each
// level is written out, and three covers any realistic navigation.
//
// NOTE: the style block uses /* */ comments only -- // is not a CSS comment
// and silently swallows the rule that follows it.
component Nav {
  outputs {
    select(payload: { item: object; value: string })
  }

  props {
    color: string = "primary"
    size: string = "default"
    items: unknown[] = []
    active: string = ""
    orientation: string = "horizontal"
    label: string = "Main"
    collapsible: boolean = true
    toggleLabel: string = "Menu"
    class: string = ""
  }

  state expanded = false

  functions {
    shared function itemList() {
      return Array.isArray(items) ? items : []
    }

    shared function childrenOf(item) {
      return item && Array.isArray(item.items) ? item.items : []
    }

    shared function isActive(item) {
      return Boolean(item.value) && item.value === active
    }

    shared function rovingAxis() {
      return orientation === "vertical" ? "vertical" : "horizontal"
    }

    client function choose(item) {
      if (item.disabled) {
        return
      }
      output.select({ item: item, value: item.value || "" })
    }

    client function toggleMenu() {
      expanded = !expanded
    }
  }

  view {
    <nav
      {...attrs}
      data-ui-component="Nav"
      class='wire-nav {class}'
      data-orientation='{orientation}'
      data-color='{color}'
      data-size='{size}'
      data-expanded='{expanded}'
      role="navigation"
      aria-label='{label}'
    >
      <button
        type="button"
        class="wire-nav__toggle"
        data-show="collapsible"
        aria-expanded='{expanded}'
        aria-label='{toggleLabel}'
        @click='toggleMenu()'
      >
        <span class="wire-nav__toggle-bar" aria-hidden="true"></span>
        <span class="wire-nav__toggle-text">{toggleLabel}</span>
      </button>

      <ul class="wire-nav__list" data-wrn-roving='{rovingAxis()}'>
        {#each itemList() as item}
          <li class="wire-nav__item" data-has-children='{childrenOf(item).length > 0}'>
            <a
              class="wire-nav__link"
              href='{item.href || "#"}'
              data-wrn-roving-item="true"
              data-active='{isActive(item)}'
              aria-current='{isActive(item) ? "page" : "false"}'
              aria-disabled='{item.disabled ? "true" : "false"}'
              @click='choose(item)'
            >
              <span
                class='wire-nav__icon {item.icon}'
                data-show="item.icon"
                aria-hidden="true"
              ></span>
              <span class="wire-nav__label">{item.label}</span>
              <span class="wire-nav__badge" data-show="item.badge">{item.badge}</span>
              <span
                class="wire-nav__arrow"
                data-show="childrenOf(item).length > 0"
                aria-hidden="true"
              >&#8250;</span>
            </a>

            <ul
              class="wire-nav__submenu"
              data-wrn-anchored="true"
              data-show="childrenOf(item).length > 0"
            >
              {#each childrenOf(item) as child}
                <li class="wire-nav__item" data-has-children='{childrenOf(child).length > 0}'>
                  <a
                    class="wire-nav__link"
                    href='{child.href || "#"}'
                    data-active='{isActive(child)}'
                    aria-current='{isActive(child) ? "page" : "false"}'
                    aria-disabled='{child.disabled ? "true" : "false"}'
                    @click='choose(child)'
                  >
                    <span
                      class='wire-nav__icon {child.icon}'
                      data-show="child.icon"
                      aria-hidden="true"
                    ></span>
                    <span class="wire-nav__label">{child.label}</span>
                    <span class="wire-nav__badge" data-show="child.badge">{child.badge}</span>
                    <span
                      class="wire-nav__arrow"
                      data-show="childrenOf(child).length > 0"
                      aria-hidden="true"
                    >&#8250;</span>
                  </a>

                  <ul
                    class="wire-nav__submenu wire-nav__submenu--level3"
                    data-wrn-anchored="true"
                    data-show="childrenOf(child).length > 0"
                  >
                    {#each childrenOf(child) as leaf}
                      <li class="wire-nav__item">
                        <a
                          class="wire-nav__link"
                          href='{leaf.href || "#"}'
                          data-active='{isActive(leaf)}'
                          aria-current='{isActive(leaf) ? "page" : "false"}'
                          aria-disabled='{leaf.disabled ? "true" : "false"}'
                          @click='choose(leaf)'
                        >
                          <span
                            class='wire-nav__icon {leaf.icon}'
                            data-show="leaf.icon"
                            aria-hidden="true"
                          ></span>
                          <span class="wire-nav__label">{leaf.label}</span>
                        </a>
                      </li>
                    {/each}
                  </ul>
                </li>
              {/each}
            </ul>
          </li>
        {/each}
      </ul>

      <slot />
    </nav>
  }

  style {
    .wire-nav {
      --nav-accent: var(--wire-color-primary);
      max-width: 100%;
    }

    .wire-nav[data-color="secondary"] {
      --nav-accent: var(--wire-color-secondary);
    }

    .wire-nav[data-color="success"] {
      --nav-accent: var(--wire-color-success);
    }

    .wire-nav[data-color="danger"] {
      --nav-accent: var(--wire-color-danger);
    }

    .wire-nav[data-color="info"] {
      --nav-accent: var(--wire-color-info);
    }

    .wire-nav[data-size="sm"] {
      font-size: 0.82rem;
    }

    .wire-nav[data-size="lg"] {
      font-size: 1rem;
    }

    .wire-nav__list {
      display: flex;
      align-items: center;
      gap: 0.25rem;
      margin: 0;
      padding: 0;
      list-style: none;
    }

    .wire-nav[data-orientation="vertical"] .wire-nav__list {
      flex-direction: column;
      align-items: stretch;
    }

    .wire-nav__item {
      position: relative;
    }

    .wire-nav__link {
      display: flex;
      align-items: center;
      gap: 0.45rem;
      padding: 0.45rem 0.7rem;
      border-radius: var(--wire-radius-sm);
      color: var(--wire-color-text-muted);
      font-size: 0.9rem;
      font-weight: 600;
      text-decoration: none;
    }

    .wire-nav__link:hover {
      background: var(--wire-color-surface-soft);
      color: var(--wire-color-text);
    }

    .wire-nav__link:focus-visible {
      outline: 2px solid var(--nav-accent);
      outline-offset: 2px;
    }

    .wire-nav__link[data-active="true"] {
      background: color-mix(in srgb, var(--nav-accent) 16%, transparent);
      color: var(--nav-accent);
    }

    .wire-nav__link[aria-disabled="true"] {
      opacity: 0.5;
      pointer-events: none;
    }

    .wire-nav__badge {
      padding: 0.05rem 0.4rem;
      border-radius: 999px;
      background: color-mix(in srgb, var(--nav-accent) 16%, transparent);
      color: var(--nav-accent);
      font-size: 0.72rem;
    }

    .wire-nav__arrow {
      display: inline-block;
      transition: transform 160ms ease;
    }

    .wire-nav__item:hover > .wire-nav__link > .wire-nav__arrow,
    .wire-nav__item:focus-within > .wire-nav__link > .wire-nav__arrow {
      transform: rotate(90deg);
    }

    .wire-nav__submenu {
      position: absolute;
      z-index: 30;
      top: 100%;
      left: 0;
      min-width: 12rem;
      margin: 0;
      padding: 0.35rem;
      border: 1px solid var(--wire-color-border);
      border-radius: var(--wire-radius-md);
      background: var(--wire-color-surface);
      box-shadow: var(--wire-shadow-1);
      list-style: none;
      opacity: 0;
      visibility: hidden;
      transition: opacity 160ms ease;
    }

    .wire-nav__item:hover > .wire-nav__submenu,
    .wire-nav__item:focus-within > .wire-nav__submenu {
      opacity: 1;
      visibility: visible;
    }

    .wire-nav__submenu--level3 {
      top: 0;
      left: 100%;
    }

    .wire-nav__toggle {
      display: none;
      align-items: center;
      gap: 0.5rem;
      padding: 0.45rem 0.7rem;
      border: 1px solid var(--wire-color-border);
      border-radius: var(--wire-radius-sm);
      background: var(--wire-color-surface);
      color: var(--wire-color-text);
      font: inherit;
      font-size: 0.9rem;
      cursor: pointer;
    }

    .wire-nav__toggle-bar {
      width: 1rem;
      height: 2px;
      background: currentColor;
      box-shadow:
        0 -5px 0 currentColor,
        0 5px 0 currentColor;
    }

    /*
     * On a phone the bar becomes a disclosure: submenus stop being floating
     * overlays and stack inline, because a hover-opened overlay is
     * unreachable on touch.
     */
    @media (max-width: 767px) {
      .wire-nav__toggle {
        display: inline-flex;
      }

      .wire-nav__list {
        flex-direction: column;
        align-items: stretch;
      }

      .wire-nav[data-expanded="false"] .wire-nav__list {
        display: none;
      }

      .wire-nav__submenu,
      .wire-nav__submenu--level3 {
        position: static;
        opacity: 1;
        visibility: visible;
        border: 0;
        box-shadow: none;
        padding-left: 1rem;
      }
    }
  }
}
