import { css, html, LitElement, nothing, svg } from "lit";
import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import { BRANCH_HEIGHT, SPACING } from "./hat-graph-const";

interface BranchConfig {
  x: number;
  height: number;
  start: boolean;
  end: boolean;
  track: boolean;
}

/**
 * @attribute active
 * @attribute track
 */
@customElement("hat-graph-branch")
export class HatGraphBranch extends LitElement {
  @property({ type: Boolean, reflect: true }) disabled = false;

  @property({ type: Boolean }) selected = false;

  @property({ type: Boolean }) start = false;

  @property({ type: Boolean }) short = false;

  @state() _branches: BranchConfig[] = [];

  private _totalWidth = 0;

  private _maxHeight = 0;

  private _updateBranches(ev: Event) {
    let total_width = 0;
    const heights: number[] = [];
    const branches: BranchConfig[] = [];
    (ev.target as HTMLSlotElement).assignedElements().forEach((c) => {
      const width = c.clientWidth;
      const height = c.clientHeight;
      branches.push({
        x: width / 2 + total_width,
        height,
        start: c.hasAttribute("graph-start"),
        end: c.hasAttribute("graph-end"),
        track: c.hasAttribute("track"),
      });
      total_width += width;
      heights.push(height);
    });
    this._totalWidth = total_width;
    this._maxHeight = Math.max(...heights);
    this._branches = branches.sort((a, b) => {
      if (a.track && !b.track) {
        return 1;
      }
      if (a.track && b.track) {
        return 0;
      }
      return -1;
    });
  }

  render() {
    return html`
      <slot name="head"></slot>
      ${!this.start
        ? html`
            <svg id="top" width=${this._totalWidth}>
              ${this._branches.map((branch) =>
                branch.start
                  ? ""
                  : svg`
                  <path
                    class=${classMap({
                      track: branch.track,
                    })}
                    d="
                      M ${this._totalWidth / 2} 0
                      L ${branch.x} ${BRANCH_HEIGHT}
                      "/>
                `
              )}
            </svg>
          `
        : nothing}
      <div id="branches">
        <svg id="lines" width=${this._totalWidth} height=${this._maxHeight}>
          ${this._branches.map((branch) => {
            if (branch.end) return "";
            return svg`
                    <path
                      class=${classMap({
                        track: branch.track,
                      })}
                      d="
                        M ${branch.x} ${branch.height}
                        v ${this._maxHeight - branch.height}
                        "/>
                  `;
          })}
        </svg>
        <slot @slotchange=${this._updateBranches}></slot>
      </div>

      ${!this.short
        ? html`
            <svg id="bottom" width=${this._totalWidth}>
              ${this._branches.map((branch) => {
                if (branch.end) return "";
                return svg`
                  <path
                    class=${classMap({
                      track: branch.track,
                    })}
                    d="
                      M ${branch.x} 0
                      V ${SPACING}
                      L ${this._totalWidth / 2} ${BRANCH_HEIGHT + SPACING}
                      "/>
                `;
              })}
            </svg>
          `
        : nothing}
    `;
  }

  static styles = css`
    :host {
      position: relative;
      display: flex;
      flex-direction: column;
      align-items: center;
    }
    :host(:focus) {
      outline: none;
    }
    #branches {
      position: relative;
      display: flex;
      flex-direction: row;
      align-items: start;
    }
    ::slotted(*) {
      z-index: 1;
    }
    ::slotted([slot="head"]) {
      margin-bottom: calc(var(--hat-graph-branch-height) / -2);
    }
    #lines {
      position: absolute;
    }
    #top {
      height: var(--hat-graph-branch-height);
    }
    #bottom {
      height: calc(var(--hat-graph-branch-height) + var(--hat-graph-spacing));
    }
    path {
      stroke: var(--stroke-clr);
      stroke-width: 2;
      fill: none;
    }
    path.track {
      stroke: var(--track-clr);
    }
    :host([disabled]) path {
      stroke: var(--disabled-clr);
    }
  `;
}

declare global {
  interface HTMLElementTagNameMap {
    "hat-graph-branch": HatGraphBranch;
  }
}
