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

/* global moment, $, document */
export const defaultFormat = "YYYY-MM-DD, HH:mm:ss";
export const isoFormatWithoutTZ = "YYYY-MM-DDTHH:mm:ss.SSS";
export const defaultFormatWithTZ = "YYYY-MM-DD, HH:mm:ss z";
export const defaultTZFormat = "z (Z)";
export const dateTimeAttrFormat = "YYYY-MM-DDThh:mm:ssTZD";

export const TimezoneEvent = "timezone";

export function formatTimezone(what) {
  if (what instanceof moment) {
    return what.isUTC() ? "UTC" : what.format(defaultTZFormat);
  }

  if (what === "UTC") {
    return what;
  }

  return moment().tz(what).format(defaultTZFormat);
}

export function isoDateToTimeEl(datetime, options) {
  const dateTimeObj = moment(datetime);

  const addTitle = $.extend({ title: true }, options).title;

  const el = document.createElement("time");
  el.setAttribute("datetime", dateTimeObj.format());
  if (addTitle) {
    el.setAttribute(
      "title",
      dateTimeObj.isUTC() ? "" : `UTC: ${dateTimeObj.clone().utc().format()}`
    );
  }
  el.innerText = dateTimeObj.format(defaultFormat);
  return el;
}

export const formatDateTime = (datetime) =>
  moment(datetime).format(defaultFormatWithTZ);

export const convertAndFormatUTC = (datetime, tz) => {
  let dateTimeObj = moment.utc(datetime);
  if (tz) dateTimeObj = dateTimeObj.tz(tz);
  return dateTimeObj.format(defaultFormatWithTZ);
};

export const secondsToString = (seconds) => {
  const numdays = Math.floor((seconds % 31536000) / 86400);
  const numhours = Math.floor(((seconds % 31536000) % 86400) / 3600);
  const numminutes = Math.floor((((seconds % 31536000) % 86400) % 3600) / 60);
  const numseconds = Math.floor((((seconds % 31536000) % 86400) % 3600) % 60);
  return (
    (numdays > 0 ? numdays + (numdays === 1 ? " day " : " days ") : "") +
    (numhours > 0 ? numhours + (numhours === 1 ? " hour " : " hours ") : "") +
    (numminutes > 0
      ? numminutes + (numminutes === 1 ? " minute " : " minutes ")
      : "") +
    (numseconds > 0
      ? numseconds + (numseconds === 1 ? " second" : " seconds")
      : "")
  );
};

export function updateAllDateTimes() {
  // Called after `moment.tz.setDefault` has changed the default TZ to display.

  $('time[data-datetime-convert!="false"]').each((_, el) => {
    const $el = $(el);
    const dt = moment($el.attr("datetime"));
    // eslint-disable-next-line no-underscore-dangle
    if (dt._isValid) {
      $el.text(
        dt.format($el.data("with-tz") ? defaultFormatWithTZ : defaultFormat)
      );
    }
    if ($el.attr("title") !== undefined) {
      // If displayed date is not UTC, have the UTC date in a title attribute
      $el.attr("title", dt.isUTC() ? "" : `UTC: ${dt.clone().utc().format()}`);
    }
  });

  // Update any date-time inputs.
  //
  // Since we have set the default timezone for moment, it will automatically
  // convert it to the new target for us
  $(".datetime input").each((_, el) => {
    el.value = moment(el.value).format();
  });
}

export function setDisplayedTimezone(tz) {
  moment.tz.setDefault(tz);
  updateAllDateTimes();
}

// moment will resolve the enddate to now if it is undefined
export const getDuration = (startDate, endDate) =>
  moment(endDate || undefined).diff(startDate || undefined);

export const formatDuration = (dur) => {
  const duration = moment.duration(dur);
  const days = duration.days();
  // .as('milliseconds') is necessary for .format() to work correctly
  return `${days > 0 ? `${days}d` : ""}${moment
    .utc(duration.as("milliseconds"))
    .format("HH:mm:ss")}`;
};

export const approxTimeFromNow = (dur) => {
  const timefromNow = moment(dur);
  return `${timefromNow.fromNow()}`;
};
