import { PktElement } from '@/base-elements/element'
import { PktSlotController } from '@/controllers/pkt-slot-controller'
import { ref } from 'lit/directives/ref.js'
import { Ref, createRef } from 'lit/directives/ref.js'
import { html, nothing, PropertyValues } from 'lit'
import { classMap } from 'lit/directives/class-map.js'
import { customElement, property, state } from 'lit/decorators.js'
import specs from 'componentSpecs/messagebox.json'

import '@/components/icon'
import { updateClassAttribute } from '@/utils/classutils'

export type TMessageboxSkin = 'beige' | 'blue' | 'red' | 'green'

export interface IPktMessagebox {
  skin?: TMessageboxSkin
  title?: string
  compact?: boolean
  closable?: boolean
}

@customElement('pkt-messagebox')
export class PktMessagebox extends PktElement implements IPktMessagebox {
  defaultSlot: Ref<HTMLElement> = createRef()

  constructor() {
    super()
    this.slotController = new PktSlotController(this, this.defaultSlot)
    this._isClosed = false
  }

  // Properties

  @property({ type: Boolean, reflect: true }) closable = specs.props.closable.default
  @property({ type: Boolean, reflect: true }) compact = specs.props.compact.default
  @property({ type: String, reflect: true }) title = ''
  @property({ type: String, reflect: true }) skin = specs.props.skin.default as TMessageboxSkin

  @state() _isClosed: boolean = false

  // Lifecycle

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

    if (_changedProperties.has('_isClosed')) {
      updateClassAttribute(this, 'pkt-hide', this._isClosed)
    }
  }

  // Render

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

    return html`<div class=${classMap(classes)}>
      ${this.closable
        ? html`<div class="pkt-messagebox__close">
            <button
              @click=${this.close}
              class="pkt-btn pkt-btn--tertiary pkt-btn--small pkt-btn--icon-only"
            >
              <pkt-icon name="close" class="pkt-link__icon"></pkt-icon>
            </button>
          </div>`
        : nothing}
      ${this.title ? html`<div class="pkt-messagebox__title">${this.title}</div>` : nothing}
      <div class="pkt-messagebox__text" ${ref(this.defaultSlot)}></div>
    </div>`
  }

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