import type { TemplateResult } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property } from "lit/decorators";
import { repeat } from "lit/directives/repeat";
import type { LabelRegistryEntry } from "../../data/label_registry";
import { computeCssColor } from "../../common/color/compute-color";
import { fireEvent } from "../../common/dom/fire_event";
import "../ha-label";
import { stringCompare } from "../../common/string/compare";
import "../chips/ha-chip-set";
import "../ha-button-menu";
import "../ha-icon";
import "../ha-list-item";

@customElement("ha-data-table-labels")
class HaDataTableLabels extends LitElement {
  @property({ attribute: false }) public labels!: LabelRegistryEntry[];

  protected render(): TemplateResult {
    const labels = this.labels.sort((a, b) => stringCompare(a.name, b.name));
    return html`
      <ha-chip-set>
        ${repeat(
          labels.slice(0, 2),
          (label) => label.label_id,
          (label) => this._renderLabel(label, true)
        )}
        ${labels.length > 2
          ? html`<ha-button-menu
              absolute
              role="button"
              tabindex="0"
              @click=${this._handleIconOverflowMenuOpened}
              @closed=${this._handleIconOverflowMenuClosed}
            >
              <ha-label slot="trigger" class="plus" dense>
                +${labels.length - 2}
              </ha-label>
              ${repeat(
                labels.slice(2),
                (label) => label.label_id,
                (label) => html`
                  <ha-list-item @click=${this._labelClicked} .item=${label}>
                    ${this._renderLabel(label, false)}
                  </ha-list-item>
                `
              )}
            </ha-button-menu>`
          : nothing}
      </ha-chip-set>
    `;
  }

  private _renderLabel(label: LabelRegistryEntry, clickAction: boolean) {
    const color = label?.color ? computeCssColor(label.color) : undefined;
    return html`
      <ha-label
        dense
        role="button"
        tabindex="0"
        .item=${label}
        @click=${clickAction ? this._labelClicked : undefined}
        @keydown=${clickAction ? this._labelClicked : undefined}
        style=${color ? `--color: ${color}` : ""}
      >
        ${label?.icon
          ? html`<ha-icon slot="icon" .icon=${label.icon}></ha-icon>`
          : nothing}
        ${label.name}
      </ha-label>
    `;
  }

  private _labelClicked(ev) {
    ev.stopPropagation();
    if (ev.type === "keydown" && ev.key !== "Enter" && ev.key !== " ") {
      return;
    }
    const label = (ev.currentTarget as any).item as LabelRegistryEntry;
    fireEvent(this, "label-clicked", { label });
  }

  protected _handleIconOverflowMenuOpened(e) {
    e.stopPropagation();
    // If this component is used inside a data table, the z-index of the row
    // needs to be increased. Otherwise the ha-button-menu would be displayed
    // underneath the next row in the table.
    const row = this.closest(".mdc-data-table__row") as HTMLDivElement | null;
    if (row) {
      row.style.zIndex = "1";
    }
  }

  protected _handleIconOverflowMenuClosed() {
    const row = this.closest(".mdc-data-table__row") as HTMLDivElement | null;
    if (row) {
      row.style.zIndex = "";
    }
  }

  static styles = css`
    :host {
      display: block;
      flex-grow: 1;
      margin-top: 4px;
      height: 22px;
    }
    ha-chip-set {
      position: fixed;
      flex-wrap: nowrap;
    }
    ha-label {
      --ha-label-background-color: var(--color, var(--grey-color));
      --ha-label-background-opacity: 0.5;
    }
    ha-button-menu {
      border-radius: 10px;
    }
    .plus {
      --ha-label-background-color: transparent;
      border: 1px solid var(--divider-color);
    }
  `;
}

declare global {
  interface HTMLElementTagNameMap {
    "ha-data-table-labels": HaDataTableLabels;
  }
  interface HASSDomEvents {
    "label-clicked": { label: LabelRegistryEntry };
  }
}
