/*
 * 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 -------------------------------------------------------

  /**
   * JSF's component separator constant
   */
  static readonly COMPONENT_SEP = ':';

  /**
   * Tobago's sub-coponent separator constant
   */
  static readonly SUB_COMPONENT_SEP = '::';

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

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

  static isSubmit = false;

  static initMarker = false;

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

  /**
   * 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(DomUtils.page().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]();
    }
  };
}
