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

export class CommandMap {

  commands: Map<string, Command>;

  // XXX remove me later... may be, if using "Custom Elements"
  /** @deprecated */
  public static getData(element: HTMLElement, eventType: string): Command {
    const commandMap: CommandMap = new CommandMap(element.dataset["tobagoCommands"]);
    return commandMap.commands.get(eventType);
  }

  static change(event: TextEvent) {
    const element = event.currentTarget as HTMLElement;
    const change = CommandMap.getData(element, "change");

    if (change.execute || change.render) {
      jsf.ajax.request(
          element.getAttribute("name"),
          event,
          {
            "javax.faces.behavior.event": "change",
            execute: change.execute,
            render: change.render
          });
    } else {
      Command.submitAction(this, change.action, change);
    }
  }

  static resize(event: Event) { // TBD MouseEvent?
    const element = event.currentTarget as HTMLElement;
    const resize = CommandMap.getData(element, "resize");
    console.debug("window resize event: " + resize);
    Command.submitAction(this, resize.action, resize);
  }

  static otherEvent(event: Event) {
    const element = event.currentTarget as HTMLElement;
    const command = CommandMap.getData(element, event.type);

    const confirmation = command.confirmation;
    if (confirmation) {
      if (!confirm(confirmation)) {
        event.preventDefault();
        return;
      }
    }
    const collapse = command.collapse;
    if (collapse) {
      Collapse.execute(collapse);
    }

    if (!command.omit) {
      const popup = command.popup;
      if (popup && popup.command === "close" && popup.immediate) {
        Popup.close(this);
      } else {
        const action = command.action ? command.action : element.id;
        if (command.execute || command.render) {
          Command.preparePartialOverlay(command);
          jsf.ajax.request(
              action,
              event,
              {
                "javax.faces.behavior.event": event.type,
                execute: command.execute,
                render: command.render
              });
        } else {
          Command.submitAction(this, action, command);
        }
        if (popup && popup.command === "close") {
          Popup.close(this);
        }
      }
    }
  }

  constructor(data: string) {
    this.commands = new Map<string, Command>();
    const object = JSON.parse(data);
    for (let key of Object.keys(object)) {
      const command5 = new Command(object[key]);
      this.commands.set(key, command5);
    }
  }

  get change() {
    return this.commands.get("change");
  }

  get complete() {
    return this.commands.get("complete");
  }

  get load() {
    return this.commands.get("load");
  }

  get resize() {
    return this.commands.get("resize");
  }

  public stringify(): string {
    let object = Object.create(null);
    for (let [k, v] of this.commands) {
      object[k] = v;
    }
    const outer = JSON.stringify(this);
    // remove {} and replace with object-JSON
    return outer.substring(0, outer.length - 3) + JSON.stringify(object) + "}";
  }
}

export class Command {

  // XXX this is a state of the page
  static isSubmit: boolean = false;

  confirmation: string;
  collapse: boolean;
  omit: boolean;
  popup; // todo: type
  action: string;
  execute: string;
  render: string;
  transition: boolean;
  delay: number;
  target: string;

  /**
   * Submitting the page with specified actionId.
   * options.transition
   * options.target
   */
  public static submitAction = function (source: any, actionId: string, command: Command = new Command()) {

    let transition = command.transition === undefined || command.transition;

    Transport.request(function () {
      if (!Command.isSubmit) {
        Command.isSubmit = true;
        const form = document.getElementsByTagName("form")[0] as HTMLFormElement;
        var oldTarget = form.getAttribute("target");
        const sourceHidden = document.getElementById("javax.faces.source") as HTMLInputElement;
        sourceHidden.disabled = false;
        sourceHidden.value = actionId;
        if (command.target) {
          form.setAttribute("target", command.target);
        }
        this.oldTransition = this.transition;
        this.transition = transition && !command.target;

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

  static initEnter(element: HTMLElement) {
    for (const page of DomUtils.selfOrQuerySelectorAll(element, ".tobago-page")) {
      page.addEventListener("keypress", function (event: KeyboardEvent) {
        let code = event.which; // XXX deprecated
        if (code === 0) {
          code = event.keyCode;
        }
        if (code === 13) {
          let target = event.target as HTMLElement;
          if (target.tagName === "A" || target.tagName === "BUTTON") {
            return;
          }
          if (target.tagName === "TEXTAREA") {
            if (!event.metaKey && !event.ctrlKey) {
              return;
            }
          }
          const name = target.getAttribute("name");
          let id = name ? name : target.id;
          while (id != null) {
            const command = document.querySelector("[data-tobago-default='" + id + "']");
            if (command) {
              command.dispatchEvent(new MouseEvent("click"));
              break;
            }
            id = Tobago4Utils.getNamingContainerId(id);
          }
          return false;
        }
      });
    }
  }

  static init = function (element: HTMLElement) {
    Command.initialize(element, false);
  };

  static initialize = function (element: HTMLElement, force: boolean) {

    for (const commandElement of DomUtils.selfOrQuerySelectorAll(element, "[data-tobago-commands]")) {

      // TODO hack to set command eventListeners after tobago-tab EventListeners
      if (force || commandElement.parentElement.tagName !== "TOBAGO-TAB") {

        const commandMap = new CommandMap(commandElement.dataset["tobagoCommands"]);

        for (const entry of commandMap.commands.entries()) {
          const key: string = entry[0];
          const value: Command = entry[1];

          switch (key) {
            case "change":
              commandElement.addEventListener("change", CommandMap.change);
              break;
            case "complete":
              if (parseFloat(commandElement.getAttribute("value")) >= parseFloat(commandElement.getAttribute("max"))) {
                if (commandMap.complete.execute || commandMap.complete.render) {
                  jsf.ajax.request(
                      this.id,
                      null,
                      {
                        "javax.faces.behavior.event": "complete",
                        execute: commandMap.complete.execute,
                        render: commandMap.complete.render
                      });
                } else {
                  Command.submitAction(this, commandMap.complete.action, commandMap.complete);
                }
              }
              break;
            case "load":
              setTimeout(function () {
                    Command.submitAction(this, commandMap.load.action, commandMap.load);
                  },
                  commandMap.load.delay || 100);
              break;
            case "resize":
              window.addEventListener("resize", CommandMap.resize);
              break;
            default:
              commandElement.addEventListener(key, CommandMap.otherEvent);
          }
        }
      }
    }
  };

  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;
        }
    */
    Command.isSubmit = true;

    Setup.onBeforeUnload();

    return true;
  };

  static preparePartialOverlay = function (command: Command) {
    if (command.transition === undefined || command.transition == null || command.transition) {
      console.debug("[tobago-command] render: '" + command.render + "'");
      if (command.render) {
        let partialIds = command.render.split(" ");
        for (let i = 0; i < partialIds.length; i++) {
          new Overlay(document.getElementById(partialIds[i]), true);
        }
      }
    }
  };

  constructor(data?: string | object) {
    let object;
    if (data) {
      if (typeof data === "string") {
        object = JSON.parse(data);
      } else {
        object = data;
      }
      for (let key of Object.keys(object)) {
        this[key] = object[key];
      }
    }
  }

  public stringify(): string {
    return JSON.stringify(this);
  }
}

Listener.register(Command.initEnter, Phase.DOCUMENT_READY);

Listener.register(Command.init, Phase.DOCUMENT_READY, Order.LATER);
Listener.register(Command.init, 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]();
    }
  };
}
