import { html, TemplateResult } from 'lit'
import { nanoid } from 'nanoid'
import { DemoPage } from '../../src/demo/DemoPage.js'
import { reactive } from '../../src/decorators/index.js'
import { ISplitLayout, SplitLayout } from '../../src/elements/layout/SplitLayout.js'
import { SplitItem } from '../../src/elements/layout/SplitItem.js'
import '../../src/md/button/ui-button.js'
import { SplitCloseDirection } from '../../src/elements/layout/type.js'

const storeKey = 'api-client.demo.layout.state'

class ComponentDemoPage extends DemoPage {
  override accessor componentName = 'Split layout'

  @reactive() accessor initialized = false

  protected layout = new SplitLayout({
    dragTypes: ['text/kind', 'text/key'],
    constrain: true,
    stateCallback: this.handlerLayoutStore.bind(this),
  })

  constructor() {
    super()
    this.initialize()
  }

  async initialize(): Promise<void> {
    this.layout.addEventListener('change', this.renderHandler.bind(this))
    this.layout.addEventListener('nameitem', this.nameLayoutItemHandler.bind(this))
    const state = this.restoreValues()
    this.layout.initialize(state)
    this.initialized = true
  }

  restoreValues(): ISplitLayout | undefined {
    const data = localStorage.getItem(storeKey)
    if (!data) {
      return undefined
    }
    try {
      return JSON.parse(data) as ISplitLayout
    } catch {
      // ...
    }
    return undefined
  }

  protected async handlerLayoutStore(state: ISplitLayout): Promise<void> {
    console.log('State change', state)
    try {
      localStorage.setItem(storeKey, JSON.stringify(state))
    } catch {
      // ...
    }
  }

  protected renderHandler(): void {
    this.render()
  }

  protected nameLayoutItemHandler(event: Event): void {
    const item = (event as CustomEvent).detail as SplitItem
    if (item.kind === 'data#itemA') {
      item.label = 'Item A'
    } else if (item.kind === 'data#itemB') {
      item.label = 'Item B'
    }
    console.log('nameLayoutItemHandler', item)
  }

  protected handleDragStart(e: DragEvent): void {
    const item = e.currentTarget as HTMLElement
    const { key, kind } = item.dataset
    if (!key || !kind) {
      return
    }
    const dt = e.dataTransfer
    if (!dt) {
      return
    }
    dt.effectAllowed = 'copyLink'
    dt.setData('text/kind', kind)
    dt.setData('text/key', key)
  }

  protected handleAddItem(): void {
    const key = nanoid()
    const kind = 'data#item'
    this.layout.addItem({ key, kind, label: 'Added item' })
  }

  protected handleReset(): void {
    this.layout.items = []
    this.layout.definitions = new Map()
    this.layout.scheduleStore()
    this.render()
  }

  protected handleClose2Left(): void {
    const { layout } = this
    const panel = layout.activePanel
    if (!panel) {
      return
    }
    if (!panel.selected) {
      return
    }
    panel.removeRelative(panel.selected, SplitCloseDirection.left)
  }

  protected handleClose2Right(): void {
    const { layout } = this
    const panel = layout.activePanel
    if (!panel) {
      return
    }
    if (!panel.selected) {
      return
    }
    panel.removeRelative(panel.selected, SplitCloseDirection.right)
  }

  contentTemplate(): TemplateResult {
    if (!this.initialized) {
      return html`<p>Loading demo page.</p>`
    }
    return html`
      <a href="../">Back</a>
      <div class="demo-container">
        ${this.renderOptions()}
        <section aria-label="demo-content" class="layout-view">${this.renderLayout()}</section>
      </div>
    `
  }

  protected renderLayout(): TemplateResult[] {
    const { layout } = this
    if (layout.isEmpty()) {
      return [this.renderEmptyLayout()]
    }
    return layout.render(this.renderItem.bind(this))
  }

  protected renderEmptyLayout(): TemplateResult {
    return html`
      <div class="empty-layout surface1">
        <p class="body-large">The layout is empty.</p>
      </div>
    `
  }

  protected renderItem(item: SplitItem, visible: boolean): TemplateResult {
    switch (item.kind) {
      default:
        return html`<p ?hidden="${!visible}" data-key="${item.key}">
          Rendering: ${item.label} ${item.kind} ${item.key}
        </p>`
    }
  }

  protected renderOptions(): TemplateResult {
    return html`
      <section aria-label="Demo control" class="data-control">
        <h2 class="title-medium">Data control</h2>
        <h3 class="title-small">Imperative API</h3>
        <ui-button color="outlined" @click="${this.handleAddItem}">Add item to current</ui-button>
        <ui-button color="outlined" @click="${this.handleReset}">Reset</ui-button>
        <ui-button color="outlined" @click="${this.handleClose2Left}">Close to left (selected)</ui-button>
        <ui-button color="outlined" @click="${this.handleClose2Right}">Close to right (selected)</ui-button>

        <h3 class="title-small">Declarative API</h3>
        <p>Items on the list can be dragged onto the layout.</p>
        <nav aria-label="drag and drop items">
          <ul class="draggable-items">
            <li data-kind="data#itemA" data-key="item-a" draggable="true" @dragstart="${this.handleDragStart}">
              Item A
            </li>
            <li data-kind="data#itemB" data-key="item-b" draggable="true" @dragstart="${this.handleDragStart}">
              Item B
            </li>
          </ul>
        </nav>
      </section>
    `
  }
}

const instance = new ComponentDemoPage()
instance.render()
