import { classMap } from 'lit/directives/class-map.js'
import { customElement, property, state } from 'lit/decorators.js'
import { html, nothing, PropertyValues } from 'lit'
import { PktElementWithSlot } from '@/base-elements/element-with-slot'
import { slotContent } from '@/directives/slot-content'
import type { TAriaLive, TAlertSkin } from 'shared-types'
import { updateClassAttribute } from '@/utils/classutils'
import specs from 'componentSpecs/alert.json'

import '@/components/icon'
import '@/components/button'

export type { TAlertSkin }

export interface IPktAlert {
  skin?: TAlertSkin
  closeAlert?: boolean
  title?: string
  date?: string | null
  ariaLive?: TAriaLive | null
  compact?: boolean
  role?: string
}
export class PktAlert extends PktElementWithSlot implements IPktAlert {
  constructor() {
    super()
    this._isClosed = false
  }

  // Properties

  @property({ type: Boolean, reflect: false }) compact = specs.props.compact.default
  @property({ type: String, reflect: true }) title: string = ''
  @property({ type: String, reflect: true }) skin: TAlertSkin = specs.props.skin
    .default as TAlertSkin
  @property({ type: String }) ariaLive: TAriaLive = specs.props.ariaLive.default as TAriaLive
  @property({ type: String, reflect: true, attribute: 'aria-live' })
  ariaLiveAttr: TAriaLive | null = null
  @property({ type: Boolean, reflect: true }) closeAlert = specs.props.closeAlert.default
  @property({ type: String, reflect: true }) date: string | null = null
  @property({ type: String, reflect: true }) role: string = 'status'

  @state() _isClosed: boolean = false

  // Lifecycle

  connectedCallback(): void {
    super.connectedCallback()
    this.ariaLiveAttr = (this.getAttribute('aria-live') as TAriaLive) || this.ariaLive
  }

  attributeChangedCallback(name: string, _old: string | null, value: string | null): void {
    if (name === 'ariaLive') {
      this.ariaLiveAttr = value as TAriaLive
    }
    super.attributeChangedCallback(name, _old, value)
  }

  protected updated(_changedProperties: PropertyValues): void {
    super.updated(_changedProperties)
    if (_changedProperties.has('ariaLive')) {
      this.ariaLiveAttr = this.ariaLive
    }
    if (_changedProperties.has('_isClosed')) {
      updateClassAttribute(this, 'pkt-hide', this._isClosed)
    }
  }

  // Render

  render() {
    const classes = {
      'pkt-alert': true,
      'pkt-alert--compact': this.compact,
      [`pkt-alert--${this.skin}`]: this.skin,
      'pkt-hide': this._isClosed,
    }

    const gridClasses = {
      'pkt-alert__grid': true,
      'pkt-alert__noTitle': !this.title,
      'pkt-alert__noDate': !this.date,
    }

    return html`
      <div class=${classMap(classes)} aria-live=${this.ariaLiveAttr}>
        <div class=${classMap(gridClasses)}>
          <pkt-icon
            class="pkt-alert__icon"
            aria-hidden="true"
            name=${this.skin === 'info' ? 'alert-information' : `alert-${this.skin}`}
          ></pkt-icon>

          ${this.closeAlert
            ? html`
                <div class="pkt-alert__close">
                  <pkt-button
                    tabindex="0"
                    aria-label="close"
                    size=${this.compact ? 'small' : 'medium'}
                    type="button"
                    skin="tertiary"
                    iconName="close"
                    variant="icon-only"
                    @click=${this.close}
                  >
                    <span class="sr-only">Lukk</span>
                  </pkt-button>
                </div>
              `
            : nothing}
          ${this.title ? html`<div class="pkt-alert__title">${this.title}</div>` : nothing}

          <div class="pkt-alert__text">${slotContent(this)}</div>

          ${this.date
            ? html`<div class="pkt-alert__date">Sist oppdatert: ${this.date}</div>`
            : nothing}
        </div>
      </div>
    `
  }

  // Methods

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

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