import { LitElement, PropertyValues, TemplateResult, html } from 'lit'
import { property } from 'lit/decorators.js'
import { LiveData } from '../../../reactive/LiveData.js'
import { type FileBreadcrumb } from '@api-client/core/models/store/File.js'
import { FolderKind } from '@api-client/core/models/kinds.js'

import '@material/web/iconbutton/icon-button.js'
import '@material/web/icon/icon.js'
import '@material/web/focus/md-focus-ring.js'

/**
 * @fires navigate - Dispatched when a navigation item is activated.
 *    The detail object is the `FileBreadcrumb` interface. The root object has the `id` set to empty string.
 */
export default class Breadcrumbs extends LitElement {
  static override shadowRootOptions: ShadowRootInit = {
    mode: 'open',
    delegatesFocus: true,
  }

  /**
   * The list of breadcrumbs to render.
   * The breadcrumbs should be ordered from the root to the current folder.
   */
  @property({ type: Object }) accessor breadcrumbs: LiveData<FileBreadcrumb[]> | undefined

  /**
   * When set it renders the special root folder with the name set on this property.
   * When the root object is clicked then the `navigate` event is dispatched without the `key` property set.
   * @attribute root-name
   */
  @property({ type: String, attribute: 'root-name' }) accessor rootName: string | undefined

  constructor() {
    super()
    this.role = 'navigation'
    this.ariaLabel = 'Breadcrumbs'
    this.handleLiveData = this.handleLiveData.bind(this)
  }

  protected override updated(cp: PropertyValues<this>): void {
    if (cp.has('breadcrumbs')) {
      const old = cp.get('breadcrumbs')
      if (old) {
        old.removeEventListener('update', this.handleLiveData)
      }
      if (this.breadcrumbs) {
        this.breadcrumbs.addEventListener('update', this.handleLiveData)
      }
    }
  }

  handleLiveData(): void {
    this.requestUpdate()
  }

  protected handleLinkClick(e: Event): void {
    const target = e.target as HTMLElement
    const { key, kind } = target.dataset
    if (kind === 'root') {
      this.navigateRoot()
      return
    }
    if (!key) {
      return
    }
    this.navigate(key)
  }

  navigate(key: string): void {
    const { breadcrumbs } = this
    if (!breadcrumbs) {
      return
    }
    const item = breadcrumbs.value.find((i) => i.key === key)
    if (!item) {
      return
    }
    this.dispatchEvent(new CustomEvent<FileBreadcrumb>('navigate', { detail: item }))
  }

  navigateRoot(): void {
    this.dispatchEvent(
      new CustomEvent<Partial<FileBreadcrumb>>('navigate', {
        detail: {
          kind: 'root',
          name: this.rootName as string,
        },
      })
    )
  }

  protected override render(): TemplateResult {
    const { breadcrumbs, rootName } = this
    const items = Array.from(breadcrumbs?.value || []).filter((i) => i.kind === FolderKind)
    if (rootName) {
      items.unshift({ key: '', name: rootName, kind: 'root' })
    }
    return html`
      <div class="container" role="list">
        ${items.map((item, index) => {
          return this.renderItem(item, index === items.length - 1)
        })}
      </div>
    `
  }

  renderItem(item: FileBreadcrumb, isLast = false): TemplateResult {
    const content = isLast ? this.renderButton(item) : this.renderLink(item)
    return html`
      <div class="item spacing-headline-small" role="listitem">${content}</div>
      ${isLast ? '' : this.renderSeparator()}
    `
  }

  renderLink(item: FileBreadcrumb): TemplateResult {
    const { key, kind, name } = item
    return html`
      <div
        tabindex="0"
        role="link"
        data-key="${key}"
        data-kind="${kind}"
        class="link-button"
        @click="${this.handleLinkClick}"
      >
        <md-focus-ring part="focus-ring"></md-focus-ring>
        ${name}
      </div>
    `
  }

  renderButton(item: FileBreadcrumb): TemplateResult {
    const { key, kind, name } = item
    return html`
      <div tabindex="0" role="button" data-key="${key}" data-kind="${kind}" class="action-button" aria-current="page">
        <md-focus-ring part="focus-ring"></md-focus-ring>
        ${name}
      </div>
    `
  }

  renderSeparator(): TemplateResult {
    return html`<md-icon class="separator">chevron_right</md-icon>`
  }
}
