/*
 * 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 {Page} from "./tobago-page";
import {DomUtils} from "./tobago-utils";

export class Focus extends HTMLElement {

  /**
   * The focusListener to set the lastFocusId must be implemented in the appropriate web elements.
   * @param event
   */
  static setLastFocusId(event: FocusEvent): void {
    const target = event.target as HTMLElement;
    let computedStyle = getComputedStyle(target);

    if (target.getAttribute("type") !== "hidden"
        && target.getAttributeNames().indexOf("disabled") === -1
        && target.getAttribute("tabindex") !== "-1"
        && computedStyle.visibility !== "hidden"
        && computedStyle.display !== "none") {
      const root = target.getRootNode() as ShadowRoot | Document;
      const tobagoFocus = root.getElementById(Page.page().id + DomUtils.SUB_COMPONENT_SEP + "lastFocusId");
      tobagoFocus.querySelector("input").value = target.id;
    }
  }

  constructor() {
    super();
  }

  /**
   * Sets the focus to the requested element or to the first possible if
   * no element is explicitly requested.
   *
   * The priority order is:
   * - error (the first error element gets the focus)
   * - auto (the element with the tobago tag attribute focus="true" gets the focus)
   * - last (the element from the last request with same id gets the focus, not AJAX)
   * - first (the first input element (without tabindex=-1) gets the focus, not AJAX)
   */
  connectedCallback(): void {
    const errorElement = this.errorElement;
    if (errorElement) {
      errorElement.focus();
      return;
    }

    if (this.autofocusElements.length > 0) {
      // nothing to do, because the browser make the work.
      return;
    }

    const lastFocusedElement = this.lastFocusedElement;
    if (lastFocusedElement) {
      lastFocusedElement.focus();
      return;
    }

    const focusableElement = this.focusableElement;
    if (focusableElement) {
      focusableElement.focus();
      return;
    }
  }

  private get errorElement(): HTMLElement {
    const root = this.getRootNode() as ShadowRoot | Document;
    const elements = root.querySelectorAll(
        ".tobago-messages-container .border-danger:not([disabled]):not([tabindex='-1'])") as NodeListOf<HTMLElement>;

    for (const element of elements) {
      const computedStyle = getComputedStyle(element);
      if (computedStyle.display !== "none" && computedStyle.visibility !== "hidden") {
        return element;
      }
    }
  }

  private get autofocusElements(): NodeListOf<HTMLElement> {
    const root = this.getRootNode() as ShadowRoot | Document;
    return root.querySelectorAll("[autofocus]");
  }

  private get lastFocusedElement(): HTMLElement {
    const lastFocusId: string = this.hiddenInput.value;
    const root = this.getRootNode() as ShadowRoot | Document;
    return root.getElementById(lastFocusId);
  }

  private get hiddenInput(): HTMLInputElement {
    return this.querySelector("input");
  }

  private get focusableElement(): HTMLElement {
    const root = this.getRootNode() as ShadowRoot | Document;
    const elements = root.querySelectorAll(
        "input:not([type='hidden']):not([disabled]):not([tabindex='-1'])," +
        "select:not([disabled]):not([tabindex='-1'])," +
        "textarea:not([disabled]):not([tabindex='-1'])") as NodeListOf<HTMLElement>;

    for (const element of elements) {
      if (this.isVisible(element)) {
        return element;
      }
    }
  }

  private isVisible(element: HTMLElement): boolean {
    const computedStyle = getComputedStyle(element);
    if (computedStyle.display === "none" || computedStyle.visibility === "hidden") {
      return false;
    } else if (element.parentElement) {
      return this.isVisible(element.parentElement);
    } else {
      return true;
    }
  }
}

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