/*
 * 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 {Listener, Phase, Order} from "./tobago-listener";
import {Overlay} from "./tobago-overlay";
import {DomUtils, Tobago4Utils} from "./tobago-utils";

export class Tobago {
  /**
   * Backward compatible listener registration. In the case of an AJAX call (phase = Phase.AFTER_UPDATE)
   * this listener will be called with a jQuery-object, the new one will get an HTMLElement.
   * @deprecated since 5.0.0
   */
  static registerListener(listener, phase, order) {

    Listener.register(function (element: HTMLElement) {
      listener(jQuery(element));
    }, phase, order);
  }
}

export class Tobago4 {

  // -------- Constants -------------------------------------------------------

  /**
   * Component separator constant
   * @const
   * @type {string}
   */
  static readonly COMPONENT_SEP = ':';

  /**
   * Tobago's subComponent separator constant
   * @const
   * @type {string}
   */
  static readonly SUB_COMPONENT_SEP = '::';

  // -------- Variables -------------------------------------------------------

  /**
   * The html form object of current page.
   * set via init function
   */
  static form = null;

  static htmlIdIndex = 0;

  static createHtmlId = function () {
    var id = '__tbg_id_' + Tobago4.htmlIdIndex++;
    console.debug('created id = ' + id);
    return id;
  };

  static jsObjects = [];

  static isSubmit = false;

  static initMarker = false;

  // -------- Functions -------------------------------------------------------

  static findPage = function () {
    return jQuery(".tobago-page");
  };

  /**
   * Find a sub-element of the page. Like the form with id e.g. page::form
   * @param suffix
   */
  static findSubElementOfPage = function (suffix) {
    return jQuery(DomUtils.escapeClientId(Tobago4.findPage().attr("id") + Tobago4.SUB_COMPONENT_SEP + suffix));
  };

  /**
   * Tobago's central init function.
   * Called when the document (DOM) is ready
   */
  static init = function () {

    if (Tobago4.initMarker) {
      return;
    }
    Tobago4.initMarker = true;

    console.time("[tobago] init");

    document.querySelector("form").addEventListener('submit', Tobago4.onSubmit);

    window.addEventListener('unload', Tobago4.onUnload);

    Listener.executeDocumentReady(document.documentElement);
    /*
        for (var order = 0; order < Listeners.documentReady.length; order++) {
          var list = Listeners.documentReady[order];
          for (var i = 0; i < list.length; i++) {
            console.time("[tobago] init " + order + " " + i);
            list[i]();
            console.timeEnd("[tobago] init " + order + " " + i);
          }
        }
    */

    console.timeEnd("[tobago] init");
  };

  static onSubmit = function (listenerOptions) {
    Listener.executeBeforeSubmit();
    /*
    XXX check if we need the return false case
    XXX maybe we cancel the submit, but we continue the rest?
    XXX should the other phases also have this feature?

        var result = true; // Do not continue if any function returns false
        for (var order = 0; order < Listeners.beforeSubmit.length; order++) {
          var list = Listeners.beforeSubmit[order];
          for (var i = 0; i < list.length; i++) {
            result = list[i](listenerOptions);
            if (result === false) {
              break;
            }
          }
        }
        if (result === false) {
          this.isSubmit = false;
          return false;
        }
    */
    Tobago4.isSubmit = true;

    Tobago4.onBeforeUnload();

    return true;
  };

  static onBeforeUnload = function () {
    if (this.transition) {
      new Overlay(DomUtils.page());
    }
    this.transition = this.oldTransition;
  };

  /**
   * Wrapper function to call application generated onunload function
   */
  static onUnload = function () {

    console.info('on onload');

    if (Tobago4.isSubmit) {
      Listener.executeBeforeUnload();
    } else {
      Listener.executeBeforeExit();
    }
    /*
        var phase = this.isSubmit ? Listeners.beforeUnload : Listeners.beforeExit;

        for (var order = 0; order < phase.length; order++) {
          var list = phase[order];
          for (var i = 0; i < list.length; i++) {
            list[i]();
          }
        }
        */
  };

  /**
   * Submitting the page with specified actionId.
   * options.transition
   * options.target
   */
  static submitAction = function (source, actionId, options?) {
    options = options || {};

    var transition = options.transition === undefined || options.transition == null || options.transition;

    Transport.request(function () {
      if (!Tobago4.isSubmit) {
        Tobago4.isSubmit = true;
        const form = <HTMLFormElement>document.getElementsByTagName("form")[0];
        var oldTarget = form.getAttribute("target");
        var $sourceHidden = jQuery(DomUtils.escapeClientId("javax.faces.source"));
        $sourceHidden.prop("disabled", false);
        $sourceHidden.val(actionId);
        if (options.target) {
          form.setAttribute("target", options.target);
        }
        this.oldTransition = this.transition;
        this.transition = transition && !options.target;

        var listenerOptions = {
          source: source,
          actionId: actionId,
          options: options
        };
        var onSubmitResult = Tobago4.onSubmit(listenerOptions);
        if (onSubmitResult) {
          try {
            form.submit();
            // reset the source field after submit, to be prepared for possible next AJAX with transition=false
            $sourceHidden.prop("disabled", true);
            $sourceHidden.val();
          } catch (e) {
            Overlay.destroy(DomUtils.page().id);
            Tobago4.isSubmit = false;
            alert('Submit failed: ' + e); // XXX localization, better error handling
          }
        }
        if (options.target) {
          if (oldTarget) {
            form.setAttribute("target", oldTarget);
          } else {
            form.removeAttribute("target");
          }
        }
        if (options.target || !transition || !onSubmitResult) {
          Tobago4.isSubmit = false;
          Transport.pageSubmitted = false;
        }
      }
      if (!Tobago4.isSubmit) {
        Transport.requestComplete(); // remove this from queue
      }


    }, true);
  };

  static initDom = function (elements) {
    elements = elements.jQuery ? elements : jQuery(elements); // fixme jQuery -> ES5

    // focus
    Tobago4.initFocus(elements);

    Tobago4.initScrollPosition(elements ? elements : jQuery(".tobago-page"));
  };

  static initScrollPosition = function (elements) {
    var scrollPanels;
    if (elements.data("tobago-scroll-panel")) {
      scrollPanels = elements;
    } else {
      scrollPanels = elements.find("[data-tobago-scroll-panel]");
    }
    scrollPanels.on("scroll", function () {
      var panel = jQuery(this);
      var scrollLeft = panel.prop("scrollLeft");
      var scrollTop = panel.prop("scrollTop");
      // store the position in a hidden field
      panel.children("[data-tobago-scroll-position]").val(scrollLeft + ";" + scrollTop);
    });
    scrollPanels.each(function () {
      var panel = jQuery(this);
      const position: string = panel.children("[data-tobago-scroll-position]").val() as string;
      var sep = position.indexOf(";");
      if (sep !== -1) {
        var scrollLeft = position.substr(0, sep);
        var scrollTop = position.substr(sep + 1);
        panel.prop("scrollLeft", scrollLeft);
        panel.prop("scrollTop", scrollTop);
      }
    });
  };

// -------- Util functions ----------------------------------------------------

  /**
   * 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)
   */
  static initFocus = function (elements) {

    var $focusable = jQuery(":input:enabled:visible:not(button):not([tabindex='-1'])");
    $focusable.focus(function () {
      // remember the last focused element, for later
      Tobago4.findSubElementOfPage("lastFocusId").val(jQuery(this).attr("id"));
    });

    var $hasDanger = Tobago4Utils.selectWithJQuery(elements, '.has-danger');
    var $dangerInput = $hasDanger.find("*").filter(":input:enabled:visible:first");
    if ($dangerInput.length > 0) {
      Tobago4.setFocus($dangerInput);
      return;
    }

    var $autoFocus = Tobago4Utils.selectWithJQuery(elements, '[autofocus]');
    var hasAutoFocus = $autoFocus.length > 0;
    if (hasAutoFocus) {
      // nothing to do, because the browser make the work.

      // autofocus in popups doesn't work automatically... so we fix that here
      jQuery('.modal').on('shown.bs.modal', function () {
        Tobago4.setFocus(jQuery(this).find('[autofocus]'));
      });

      return;
    }

    if (elements) {
      // seems to be AJAX, so end here
      return;
    }

    var lastFocusId = Tobago4.findSubElementOfPage("lastFocusId").get(0).getAttribute("value");
    if (lastFocusId) {
      Tobago4.setFocus(jQuery(DomUtils.escapeClientId(lastFocusId)));
      return;
    }

    var $firstInput = jQuery(":input:enabled:visible:not(button):not([tabindex='-1']):first");
    if ($firstInput.length > 0) {
      Tobago4.setFocus($firstInput);
      return;
    }
  };

  static setFocus = function ($element) {
    try {
      // focus() on not visible elements breaks some IE
      $element.focus();
    } catch (e) {
      console.error("element-id=" + $element.attr("id") + " exception=" + e);
    }
  };

  static toString = function (element) {
    var result = '';
    for (var property in element) {
      if (property && element[property]) {
        var value = '' + element[property];
        if (value !== '') {
          result += '\r\n' + property + '=' + value;
        }
      }
    }
    return result;
  };

}

document.addEventListener('DOMContentLoaded', function () {
  Tobago4.init();
});

window.addEventListener("load", function () {
  Listener.executeWindowLoad();
});

// using Tobago.Order.LATE, because the command event generated by data-tobago-commands
// may produce a submit, but we need to do something before the submit (and also on click,
// e. g. selectOne in a toolBar).
Listener.register(Tobago4.initDom, Phase.DOCUMENT_READY, Order.LATER);
Listener.register(Tobago4.initDom, Phase.AFTER_UPDATE, Order.LATER);

class Transport {
  static requests = [];
  static currentActionId = null;
  static pageSubmitted = false;
  static startTime: Date;

  /**
   * @return true if the request is queued.
   */
  static request = function (req, submitPage, actionId?) {
    var index = 0;
    if (submitPage) {
      Transport.pageSubmitted = true;
      index = Transport.requests.push(req);
      //console.debug('index = ' + index)
    } else if (!Transport.pageSubmitted) { // AJAX case
      console.debug('Current ActionId = ' + Transport.currentActionId + ' action= ' + actionId);
      if (actionId && Transport.currentActionId === actionId) {
        console.info('Ignoring request');
        // If actionId equals currentActionId assume double request: do nothing
        return false;
      }
      index = Transport.requests.push(req);
      //console.debug('index = ' + index)
      Transport.currentActionId = actionId;
    } else {
      console.debug("else case");
      return false;
    }
    console.debug('index = ' + index);
    if (index === 1) {
      console.info('Execute request!');
      Transport.startTime = new Date();
      Transport.requests[0]();
    } else {
      console.info('Request queued!');
    }
    return true;
  };


// TBD XXX REMOVE is this called in non AJAX case?

  static requestComplete = function () {
    Transport.requests.shift();
    Transport.currentActionId = null;
    console.debug('Request complete! Duration: ' + (new Date().getTime() - Transport.startTime.getTime()) + 'ms; '
        + 'Queue size : ' + Transport.requests.length);
    if (Transport.requests.length > 0) {
      console.debug('Execute request!');
      Transport.startTime = new Date();
      Transport.requests[0]();
    }
  };
}
