import { classMap } from 'lit/directives/class-map.js'
import { customElement, property, state } from 'lit/decorators.js'
import { html, PropertyValues } from 'lit'
import { PktElementWithSlot } from '@/base-elements/element-with-slot'
import { slotContent } from '@/directives/slot-content'
import { TPktSize } from '@/types/size'
import specs from 'componentSpecs/tag.json'

import '@/components/icon'
import type { IAriaAttributes, THTMLButtonType } from 'shared-types'
import { PktIconName } from '@oslokommune/punkt-assets/dist/icons/icon'
import { ifDefined } from 'lit/directives/if-defined.js'

export type TTagSkin =
  | 'blue'
  | 'blue-dark'
  | 'blue-light'
  | 'green'
  | 'red'
  | 'yellow'
  | 'beige'
  | 'gray'
  | 'grey'
export type TTagType = THTMLButtonType

export interface IPktTag {
  closeTag?: boolean
  size?: TPktSize
  skin?: TTagSkin
  textStyle?: string | null
  iconName?: PktIconName
  type?: TTagType
  ariaLabel?: IAriaAttributes['aria-label'] | null
}

export class PktTag extends PktElementWithSlot<IPktTag> implements IPktTag {
  constructor() {
    super()
    this._isClosed = false
  }

  /**
   * Element attributes
   */
  @property({ type: Boolean, reflect: true }) closeTag: boolean = specs.props.closeTag.default
  @property({ type: String, reflect: true }) size: TPktSize = specs.props.size.default as TPktSize
  @property({ type: String, reflect: true }) skin: TTagSkin = specs.props.skin.default as TTagSkin
  @property({ type: String, reflect: true }) textStyle: string | null = null
  @property({ type: String, reflect: true }) iconName: string | undefined = undefined
  @property({ type: String }) type: TTagType = specs.props.type.default as TTagType
  @property({ type: String }) ariaLabel: string | null = null
  @property({ type: Number, attribute: 'button-tabindex' }) buttonTabindex: number | undefined =
    undefined

  /**
   * Element state
   */
  @state() _isClosed: boolean = false
  @state() _ariaDescription: string | null = null

  /**
   * Lifecycle
   */

  protected firstUpdated(_changedProperties: PropertyValues): void {
    super.firstUpdated(_changedProperties)

    if (this.closeTag && !this.ariaLabel) {
      const label = this.querySelector('button span, .pkt-tag > span')?.textContent?.trim()
      if (label) {
        this._ariaDescription = `Klikk for å fjerne ${label}`
      }
    }
  }

  /**
   * Element functions
   */
  private close = (event: MouseEvent) => {
    this._isClosed = true
    this.dispatchEvent(
      new CustomEvent('close', { detail: { origin: event }, bubbles: false, composed: true }),
    )
    // Historical support of old Vue implementations…
    this.dispatchEvent(
      new CustomEvent('on-close', { detail: { origin: event }, bubbles: false, composed: true }),
    )
  }

  render() {
    const classes = {
      'pkt-tag': true,
      [`pkt-tag--${this.size}`]: !!this.size,
      [`pkt-tag--${this.skin}`]: !!this.skin,
      [`pkt-tag--${this.textStyle}`]: !!this.textStyle,
    }

    const btnClasses = {
      'pkt-tag': true,
      'pkt-btn': true,
      'pkt-btn--tertiary': true,
      [`pkt-tag--${this.textStyle}`]: !!this.textStyle,
      [`pkt-tag--${this.size}`]: !!this.size,
      [`pkt-tag--${this.skin}`]: !!this.skin,
      'pkt-btn--icons-right-and-left': this.closeTag && !!this.iconName,
      'pkt-hide': this._isClosed,
    }

    if (this.closeTag) {
      return html`
        <button
          class=${classMap(btnClasses)}
          type=${this.type}
          tabindex=${ifDefined(this.buttonTabindex)}
          @click=${this.close}
          aria-label=${ifDefined(this.ariaLabel || undefined)}
          aria-description=${ifDefined(this._ariaDescription || undefined)}
        >
          ${this.iconName &&
          html`<pkt-icon
            class="pkt-tag__icon"
            name=${this.iconName}
            aria-hidden="true"
          ></pkt-icon>`}
          <span>${slotContent(this)}</span>
          <pkt-icon class="pkt-tag__close-btn" name="close"></pkt-icon>
        </button>
      `
    } else {
      return html`
        <span class=${classMap(classes)}>
          ${this.iconName &&
          html`<pkt-icon
            class="pkt-tag__icon"
            name=${this.iconName}
            aria-hidden="true"
          ></pkt-icon>`}
          <span>${slotContent(this)}</span>
        </span>
      `
    }
  }
}

try {
  customElement('pkt-tag')(PktTag)
} catch (e) {
  console.warn('Forsøker å definere <pkt-tag>, men den er allerede definert')
}
