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

class DateTime {

  static init(element: HTMLElement): void {
    for (const e of DomUtils.selfOrQuerySelectorAll(element, ".tobago-date:not([readonly]):not([disabled])")) {
      const date: HTMLInputElement = e as HTMLInputElement;

      const analyzed = DateTime.analyzePattern(date.dataset.tobagoPattern);
      const options = {
        format: analyzed,
        showTodayButton: date.dataset.tobagoTodayButton === "data-tobago-today-button",
        icons: {
          time: "fa fa-clock-o",
          date: "fa fa-calendar",
          up: "fa fa-chevron-up",
          down: "fa fa-chevron-down",
          previous: "fa fa-chevron-left",
          next: "fa fa-chevron-right",
          today: "fa fa-calendar-check-o",
          clear: "fa fa-trash",
          close: "fa fa-times"
        },
        keyBinds: {
          left: function ($widget): void {
            const widget: HTMLDivElement = $widget[0] as HTMLDivElement;
            if (widget === undefined) {
              if (date.selectionStart === date.selectionEnd) {
                if (date.selectionStart > 0 || date.selectionStart > 0) {
                  date.selectionStart--;
                  date.selectionEnd--;
                }
              } else {
                date.selectionEnd = date.selectionStart;
              }
            } else if (DomUtils.isVisible(widget.querySelector(".datepicker"))) {
              this.date(this.date().clone().subtract(1, "d"));
            }
          },
          right: function ($widget): void {
            const widget: HTMLDivElement = $widget[0] as HTMLDivElement;
            if (widget === undefined) {
              if (date.selectionStart === date.selectionEnd) {
                if (date.selectionStart > 0 || date.selectionStart < date.value.length) {
                  date.selectionEnd++;
                  date.selectionStart++;
                }
              } else {
                date.selectionStart = date.selectionEnd;
              }
            } else if (DomUtils.isVisible(widget.querySelector(".datepicker"))) {
              this.date(this.date().clone().add(1, "d"));
            }
          },
          enter: function ($widget): void {
            const widget: HTMLDivElement = $widget[0] as HTMLDivElement;
            if (widget !== undefined && DomUtils.isVisible(widget.querySelector(".datepicker"))) {
              this.hide();
              fixKey(13);
            } else {
              //jQuery because used by datetimepicker
              jQuery(date).trigger(jQuery.Event("keypress", {
                which: 13,
                target: date
              }));
            }
          },
          escape: function ($widget): void {
            const widget: HTMLDivElement = $widget[0] as HTMLDivElement;
            if (widget !== undefined && DomUtils.isVisible(widget.querySelector(".datepicker"))) {
              this.hide();
              fixKey(27);
            }
          },
          "delete": function (): void {
            if (date.selectionStart < date.value.length) {
              const selectionStart = date.selectionStart;
              let selectionEnd = date.selectionEnd;

              if (selectionStart === selectionEnd && selectionStart < date.value.length) {
                selectionEnd++;
              }
              date.value = date.value.substr(0, selectionStart)
                  + date.value.substr(selectionEnd, date.value.length);

              date.selectionEnd = selectionStart;
              date.selectionStart = selectionStart;
            }
          }
        },
        widgetParent: ".tobago-page-menuStore"
      };

      /**
       * After ESC or ENTER is pressed we need to fire the keyup event manually.
       * see: https://github.com/tempusdominus/bootstrap-4/issues/159
       */
      function fixKey(keyCode): void {
        let keyupEvent = jQuery.Event("keyup");
        keyupEvent.which = keyCode;
        jQuery(date).trigger(keyupEvent);
      }

      const i18n = date.dataset.tobagoDateTimeI18n ? JSON.parse(date.dataset.tobagoDateTimeI18n) : undefined;
      if (i18n) {
        const monthNames = i18n.monthNames;
        if (monthNames) {
          moment.localeData()._months = monthNames;
        }
        const monthNamesShort = i18n.monthNamesShort;
        if (monthNamesShort) {
          moment.localeData()._monthsShort = monthNamesShort;
        }
        const dayNames = i18n.dayNames;
        if (dayNames) {
          moment.localeData()._weekdays = dayNames;
        }
        const dayNamesShort = i18n.dayNamesShort;
        if (dayNamesShort) {
          moment.localeData()._weekdaysShort = dayNamesShort;
        }
        const dayNamesMin = i18n.dayNamesMin;
        if (dayNamesMin) {
          moment.localeData()._weekdaysMin = dayNamesMin;
        }
        const firstDay = i18n.firstDay;
        if (firstDay) {
          moment.localeData()._week.dow = firstDay;
        }
      }

      let $dateParent = jQuery(date).parent(); //use jQuery because required for datetimepicker
      $dateParent.datetimepicker(options);

      // we need to add the change listener here, because
      // in line 1307 of bootstrap-datetimepicker.js
      // the 'stopImmediatePropagation()' stops the change-event
      // execution of line 686 in tobago.js
      $dateParent.on("dp.change", function (event: Event): void {
        let input: HTMLInputElement = this.querySelector("input");
        let commands = input.dataset.tobagoCommands ? JSON.parse(input.dataset.tobagoCommands) : undefined;
        if (commands && commands.change) {
          if (commands.change.execute || commands.change.render) {
            jsf.ajax.request(
                input.getAttribute("name"),
                event,
                {
                  "javax.faces.behavior.event": "change",
                  execute: commands.change.execute,
                  render: commands.change.render
                });
          } else if (commands.change.action) {
            CommandHelper.submitAction(
                this.firstElementChild as HTMLElement,
                commands.change.action, commands.change.transition, commands.change.target);
          }
        }
      });

      // set position
      $dateParent.on("dp.show", function (): void {
        let datepicker: HTMLDivElement = document.querySelector(".bootstrap-datetimepicker-widget");
        let div: HTMLDivElement = this;
        let top, left;
        if (datepicker.classList.contains("bottom")) {
          top = DomUtils.offset(div).top + div.offsetHeight;
          left = DomUtils.offset(div).left;
          datepicker.style.top = top + "px";
          datepicker.style.bottom = "auto";
          datepicker.style.left = left + "px";
        } else if (datepicker.classList.contains("top")) {
          top = DomUtils.offset(div).top - datepicker.offsetHeight;
          left = DomUtils.offset(div).left;
          datepicker.style.top = top + "px";
          datepicker.style.bottom = "auto";
          datepicker.style.left = left + "px";
        }
        DateTime.addPastClass(date);
      });

      // set css class in update - like changing the month
      $dateParent.on("dp.update", function (): void {
        DateTime.addPastClass(date);
      });

      // fix for bootstrap-datetimepicker v4.17.45
      $dateParent.on("dp.show", function (): void {
        const collapseIn = document.querySelector(".bootstrap-datetimepicker-widget .collapse.in");
        const pickerSwitch = document.querySelector(".bootstrap-datetimepicker-widget .picker-switch a");

        if (collapseIn !== null) {
          collapseIn.classList.add("show");
        }
        if (pickerSwitch !== null) {
          pickerSwitch.addEventListener(
              "click", function (): void {
                // the click is executed before togglePicker() function
                let datetimepicker: HTMLDivElement = document.querySelector(".bootstrap-datetimepicker-widget");
                datetimepicker.querySelector(".collapse.in").classList.remove("in");
                datetimepicker.querySelector(".collapse.show").classList.add("in");
              });
        }
      });
    }
  }

  static addPastClass(date: HTMLInputElement): void {
    let today = date.dataset.tobagoToday;
    if (today.length === 10) {
      const todayArray = today.split("-");
      if (todayArray.length === 3) {
        const year = todayArray[0];
        const month = todayArray[1];
        const day = todayArray[2];
        const todayTimestamp = new Date(month + "/" + day + "/" + year).getTime();

        const days = document.querySelectorAll(".bootstrap-datetimepicker-widget .datepicker-days td.day[data-day]");
        for (const day of days) {
          const currentTimestamp = new Date(day.getAttribute("data-day")).getTime();
          if (currentTimestamp < todayTimestamp) {
            day.classList.add("past");
          }
        }
      }
    }
  }

  /*
   Get the pattern from the "Java world" (http://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html)
   and convert it to 'moment.js'.
   Attention: Not every pattern char is supported.
   */
  static analyzePattern = function (originalPattern: string): string {

    let pattern;
    if (!originalPattern || originalPattern.length > 100) {
      console.warn("Pattern not supported: " + originalPattern);
      pattern = "";
    } else {
      pattern = originalPattern;
    }

    let analyzedPattern = "";
    let nextSegment = "";
    let escMode = false;
    for (let i = 0; i < pattern.length; i++) {
      const currentChar = pattern.charAt(i);
      if (currentChar == "'" && escMode == false) {
        escMode = true;
        analyzedPattern += DateTime.analyzePatternPart(nextSegment);
        nextSegment = "";
      } else if (currentChar == "'" && pattern.charAt(i + 1) == "'") {
        if (escMode) {
          nextSegment += "\\";
        }
        nextSegment += "'";
        i++;
      } else if (currentChar == "'" && escMode == true) {
        escMode = false;
        analyzedPattern += nextSegment;
        nextSegment = "";
      } else {
        if (escMode) {
          nextSegment += "\\";
        }
        nextSegment += currentChar;
      }
    }
    if (nextSegment != "") {
      if (escMode) {
        analyzedPattern += nextSegment;
      } else {
        analyzedPattern += DateTime.analyzePatternPart(nextSegment);
      }
    }

    return analyzedPattern;
  };

  static analyzePatternPart = function (originalPattern: string): string {

    let pattern = originalPattern;

    if (pattern.search("G") > -1 || pattern.search("W") > -1 || pattern.search("F") > -1
        || pattern.search("K") > -1 || pattern.search("z") > -1 || pattern.search("X") > -1) {
      console.warn("Pattern chars 'G', 'W', 'F', 'K', 'z' and 'X' are not supported: " + pattern);
      pattern = "";
    }

    if (pattern.search("y") > -1) {
      pattern = pattern.replace(/y/g, "Y");
    }
    if (pattern.search("Y") > -1) {
      pattern = pattern.replace(/\bY\b/g, "YYYY");
      pattern = pattern.replace(/\bYYY\b/g, "YY");
      pattern = pattern.replace(/YYYYYY+/g, "YYYYY");
    }

    if (pattern.search("MMMMM") > -1) {
      pattern = pattern.replace(/MMMMM+/g, "MMMM");
    }

    if (pattern.search("w") > -1) {
      pattern = pattern.replace(/\bw\b/g, "W");
      pattern = pattern.replace(/www+/g, "WW");
    }

    if (pattern.search("D") > -1) {
      pattern = pattern.replace(/DDD+/g, "DDDD");
      pattern = pattern.replace(/\bD{1,2}\b/g, "DDD");
    }

    if (pattern.search("d") > -1) {
      pattern = pattern.replace(/dd+/g, "DD");
      pattern = pattern.replace(/\bd\b/g, "D");
    }

    if (pattern.search("E") > -1) {
      pattern = pattern.replace(/\bE{1,3}\b/g, "dd");
      pattern = pattern.replace(/EEEE+/g, "dddd");
    }

    if (pattern.search("u") > -1) {
      pattern = pattern.replace(/u+/g, "E");
    }
    if (pattern.search("a") > -1) {
      pattern = pattern.replace(/a+/g, "A");
    }
    if (pattern.search("HHH") > -1) {
      pattern = pattern.replace(/HHH+/g, "HH");
    }
    if (pattern.search("kkk") > -1) {
      pattern = pattern.replace(/kkk+/g, "kk");
    }
    if (pattern.search("hhh") > -1) {
      pattern = pattern.replace(/hhh+/g, "hh");
    }
    if (pattern.search("mmm") > -1) {
      pattern = pattern.replace(/mmm+/g, "mm");
    }
    if (pattern.search("sss") > -1) {
      pattern = pattern.replace(/sss+/g, "ss");
    }
    if (pattern.search("SSSS") > -1) {
      pattern = pattern.replace(/SSSS+/g, "SSS");
    }
    if (pattern.search("Z") > -1) {
      pattern = pattern.replace(/\bZ\b/g, "ZZ");
      pattern = pattern.replace(/ZZZ+/g, "ZZ");
    }

    return pattern;
  };
}

Listener.register(DateTime.init, Phase.DOCUMENT_READY);
Listener.register(DateTime.init, Phase.AFTER_UPDATE);
