/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import {DomUtils} from "./tobago-utils";

class TreeListbox extends HTMLElement {

  constructor() {
    super();
  }

  connectedCallback(): void {
    this.applySelected();

    for (const listbox of this.listboxes) {
      if (!listbox.disabled) {
        listbox.addEventListener("change", this.select.bind(this));
      }
    }
  }

  private select(event: Event): void {
    const listbox = event.currentTarget as HTMLSelectElement;
    this.unselectDescendants(listbox);
    this.setSelected();
    this.applySelected();
  }

  private unselectDescendants(select: HTMLSelectElement): void {
    let unselect: boolean = false;
    for (const listbox of this.listboxes) {
      if (unselect) {
        const checkedOption = listbox.querySelector<HTMLOptionElement>("option:checked");
        if (checkedOption) {
          checkedOption.selected = false;
        }
      } else if (listbox.id === select.id) {
        unselect = true;
      }
    }
  }

  private setSelected(): void {
    const selected: number[] = [];
    for (const level of this.levelElements) {
      const checkedOption: HTMLOptionElement = level
          .querySelector(".tobago-treeListbox-select:not(.d-none) option:checked");
      if (checkedOption) {
        selected.push(checkedOption.index);
      }
    }
    this.hiddenInput.value = JSON.stringify(selected);
  }

  private applySelected(): void {
    const selected: number[] = JSON.parse(this.hiddenInput.value);
    let nextActiveSelect: HTMLSelectElement = this.querySelector(".tobago-treeListbox-select");

    const levelElements = this.levelElements;
    for (let i = 0; i < levelElements.length; i++) {
      const level = levelElements[i];

      for (const select of this.getSelectElements(level)) {
        if ((nextActiveSelect !== null && select.id === nextActiveSelect.id)
            || (nextActiveSelect === null && select.disabled)) {
          const check: number = i < selected.length ? selected[i] : null;
          this.show(select, check);
          nextActiveSelect = this.getNextActiveSelect(select, check);
        } else {
          this.hide(select);
        }
      }
    }
  }

  private getSelectElements(level: HTMLDivElement): NodeListOf<HTMLSelectElement> {
    return level.querySelectorAll<HTMLSelectElement>(".tobago-treeListbox-select");
  }

  private getNextActiveSelect(select: HTMLSelectElement, check: number): HTMLSelectElement {
    if (check !== null) {
      const option = select.querySelectorAll("option")[check];
      return this.querySelector(DomUtils.escapeClientId(option.id + DomUtils.SUB_COMPONENT_SEP + "parent"));
    } else {
      return null;
    }
  }

  private show(select: HTMLSelectElement, check: number): void {
    select.classList.remove("d-none");
    const checkedOption = select.querySelector<HTMLOptionElement>("option:checked");
    if (checkedOption && checkedOption.index !== check) {
      checkedOption.selected = false;
    }
    if (check !== null && checkedOption.index !== check) {
      select.querySelectorAll("option")[check].selected = true;
    }
  }

  private hide(select: HTMLSelectElement): void {
    select.classList.add("d-none");
    const checkedOption = select.querySelector<HTMLOptionElement>("option:checked");
    if (checkedOption) {
      checkedOption.selected = false;
    }
  }

  private get listboxes(): NodeListOf<HTMLSelectElement> {
    return this.querySelectorAll(".tobago-treeListbox-select");
  }

  private get levelElements(): NodeListOf<HTMLDivElement> {
    return this.querySelectorAll(".tobago-treeListbox-level");
  }

  private get hiddenInput(): HTMLInputElement {
    return this.querySelector(DomUtils.escapeClientId(this.id + DomUtils.SUB_COMPONENT_SEP + "selected"));
  }
}

document.addEventListener("DOMContentLoaded", function (event: Event): void {
  window.customElements.define("tobago-tree-listbox", TreeListbox);
});
