/**
 * StatusBar component
 * @countermeasure/web-components/components/status-bar
 */

import { setSafeHtml } from '../../utils/sanitize'

export interface StatusBarSection {
  /** Stable unique identifier passed to `update(id, data)`. */
  id: string
  /** Alignment slot inside the status bar. */
  position: 'left' | 'center' | 'right'
  /** Template invoked with the section's current data record. */
  template: (data: Record<string, unknown>) => string
}

export interface StatusBarConfig {
  /** Container element (or selector) the bar is mounted into. */
  container: HTMLElement | string
  /**
   * Initial sections.
   * @default []
   */
  sections?: StatusBarSection[]
}

function resolveContainer(container: HTMLElement | string): HTMLElement {
  if (typeof container === 'string') {
    const el = document.querySelector(container)
    if (!el) {
      throw new Error(`StatusBar: container not found for selector "${container}"`)
    }
    return el as HTMLElement
  }
  return container
}

export class StatusBar {
  private readonly containerEl: HTMLElement
  private readonly rootEl: HTMLElement
  private readonly leftEl: HTMLElement
  private readonly centerEl: HTMLElement
  private readonly rightEl: HTMLElement
  private readonly sections = new Map<string, StatusBarSection>()
  private readonly sectionElements = new Map<string, HTMLElement>()
  private destroyed = false

  constructor(config: StatusBarConfig) {
    this.containerEl = resolveContainer(config.container)

    this.rootEl = document.createElement('div')
    this.rootEl.className = 'cmm-status-bar'

    this.leftEl = document.createElement('div')
    this.leftEl.className = 'cmm-status-bar__left'

    this.centerEl = document.createElement('div')
    this.centerEl.className = 'cmm-status-bar__center'

    this.rightEl = document.createElement('div')
    this.rightEl.className = 'cmm-status-bar__right'

    this.rootEl.appendChild(this.leftEl)
    this.rootEl.appendChild(this.centerEl)
    this.rootEl.appendChild(this.rightEl)
    this.containerEl.appendChild(this.rootEl)

    if (config.sections) {
      for (const section of config.sections) {
        this.addSection(section)
      }
    }
  }

  update(sectionId: string, data: Record<string, unknown>): void {
    const section = this.sections.get(sectionId)
    const element = this.sectionElements.get(sectionId)

    if (!section || !element) {
      return
    }

    setSafeHtml(element, section.template(data), { allowSvg: true })
  }

  addSection(section: StatusBarSection): void {
    this.sections.set(section.id, section)

    const sectionEl = document.createElement('div')
    sectionEl.className = 'cmm-status-bar__section'
    sectionEl.dataset.sectionId = section.id

    this.sectionElements.set(section.id, sectionEl)

    const positionContainer = this.getPositionContainer(section.position)
    positionContainer.appendChild(sectionEl)
  }

  destroy(): void {
    if (this.destroyed) {
      return
    }
    this.destroyed = true

    if (this.rootEl.parentNode) {
      this.rootEl.parentNode.removeChild(this.rootEl)
    }

    this.sections.clear()
    this.sectionElements.clear()
  }

  private getPositionContainer(position: 'left' | 'center' | 'right'): HTMLElement {
    if (position === 'left') {
      return this.leftEl
    }
    if (position === 'center') {
      return this.centerEl
    }
    return this.rightEl
  }
}
