'use strict';

var errors = require('@backstage/errors');
var ms = require('ms');

function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }

var ms__default = /*#__PURE__*/_interopDefaultCompat(ms);

const propsOfHumanDuration = [
  "years",
  "months",
  "weeks",
  "days",
  "hours",
  "minutes",
  "seconds",
  "milliseconds"
];
function readDurationFromConfig(config, options) {
  if (options?.key && typeof config.getOptional(options.key) === "string") {
    const value = config.getString(options.key).trim();
    try {
      return value.startsWith("P") ? parseIsoDuration(value) : parseMsDuration(value);
    } catch (error) {
      throw new errors.InputError(
        `Invalid duration '${value}' in config at '${options.key}', ${errors.stringifyError(error)}`
      );
    }
  }
  return parseObjectDuration(config, options);
}
function parseObjectDuration(config, options) {
  let root;
  let found = false;
  const result = {};
  try {
    root = options?.key ? config.getConfig(options.key) : config;
    for (const prop of propsOfHumanDuration) {
      const value = root.getOptionalNumber(prop);
      if (value !== void 0) {
        result[prop] = value;
        found = true;
      }
    }
  } catch (error) {
    throw new errors.InputError(`Failed to read duration from config, ${error}`);
  }
  try {
    if (!found) {
      const good = propsOfHumanDuration.map((p) => `'${p}'`).join(", ");
      throw new Error(`Needs one or more of ${good}`);
    }
    const invalidProps = root.keys().filter((prop) => !propsOfHumanDuration.includes(prop));
    if (invalidProps.length) {
      const what = invalidProps.length === 1 ? "property" : "properties";
      const bad = invalidProps.map((p) => `'${p}'`).join(", ");
      const good = propsOfHumanDuration.map((p) => `'${p}'`).join(", ");
      throw new Error(
        `Unknown ${what} ${bad}; expected one or more of ${good}`
      );
    }
  } catch (error) {
    let prefix = "Failed to read duration from config";
    if (options?.key) {
      prefix += ` at '${options.key}'`;
    }
    throw new Error(`${prefix}, ${error}`);
  }
  return result;
}
function parseMsDuration(input) {
  if (/^\d+$/.exec(input)) {
    throw new Error(
      `The value cannot be a plain number; try adding a unit like 'ms' or 'seconds'`
    );
  }
  let milliseconds = ms__default.default(input);
  if (!Number.isFinite(milliseconds)) {
    throw new Error(
      `Not a valid duration string, try a number followed by a unit such as '1d' or '2 seconds'`
    );
  } else if (milliseconds < 0) {
    throw new Error("Negative durations are not allowed");
  } else if (milliseconds === 0) {
    return { milliseconds: 0 };
  }
  const s = 1e3;
  const m = s * 60;
  const h = m * 60;
  const d = h * 24;
  const w = d * 7;
  const y = d * 365.25;
  const result = {};
  if (milliseconds >= y) {
    const years = Math.floor(milliseconds / y);
    milliseconds -= years * y;
    result.years = years;
  }
  if (milliseconds >= w) {
    const weeks = Math.floor(milliseconds / w);
    milliseconds -= weeks * w;
    result.weeks = weeks;
  }
  if (milliseconds >= d) {
    const days = Math.floor(milliseconds / d);
    milliseconds -= days * d;
    result.days = days;
  }
  if (milliseconds >= h) {
    const hours = Math.floor(milliseconds / h);
    milliseconds -= hours * h;
    result.hours = hours;
  }
  if (milliseconds >= m) {
    const minutes = Math.floor(milliseconds / m);
    milliseconds -= minutes * m;
    result.minutes = minutes;
  }
  if (milliseconds >= s) {
    const seconds = Math.floor(milliseconds / s);
    milliseconds -= seconds * s;
    result.seconds = seconds;
  }
  if (milliseconds > 0) {
    result.milliseconds = milliseconds;
  }
  return result;
}
function parseIsoDuration(input) {
  const match = /^-?P(?:(?:(-?\d{1,20}(?:\.\d{1,20})?)Y)?(?:(-?\d{1,20}(?:\.\d{1,20})?)M)?(?:(-?\d{1,20}(?:\.\d{1,20})?)W)?(?:(-?\d{1,20}(?:\.\d{1,20})?)D)?(?:T(?:(-?\d{1,20}(?:\.\d{1,20})?)H)?(?:(-?\d{1,20}(?:\.\d{1,20})?)M)?(?:(-?\d{1,20})(?:[.,](-?\d{1,20}))?S)?)?)$/.exec(
    input
  );
  if (!match) {
    throw new Error(
      `Invalid ISO format, expected a value similar to 'P2DT6H' (2 days 6 hours) or 'PT1M' (1 minute)`
    );
  }
  const [
    s,
    yearStr,
    monthStr,
    weekStr,
    dayStr,
    hourStr,
    minuteStr,
    secondStr,
    millisecondsStr
  ] = match;
  const hasNegativePrefix = s[0] === "-";
  const negativeSeconds = !!secondStr && secondStr[0] === "-";
  const maybeNegate = (num, force = false) => num !== void 0 && (force || num && hasNegativePrefix) ? -num : num;
  const parseFloating = (value) => {
    if (typeof value === "undefined" || value === null || value === "") {
      return void 0;
    }
    return parseFloat(value);
  };
  const parseMillis = (fraction) => {
    if (typeof fraction === "undefined" || fraction === null || fraction === "") {
      return void 0;
    }
    const f = parseFloat(`0.${fraction}`) * 1e3;
    return Math.floor(f);
  };
  const years = maybeNegate(parseFloating(yearStr));
  const months = maybeNegate(parseFloating(monthStr));
  const weeks = maybeNegate(parseFloating(weekStr));
  const days = maybeNegate(parseFloating(dayStr));
  const hours = maybeNegate(parseFloating(hourStr));
  const minutes = maybeNegate(parseFloating(minuteStr));
  const seconds = maybeNegate(parseFloating(secondStr), secondStr === "-0");
  const milliseconds = maybeNegate(
    parseMillis(millisecondsStr),
    negativeSeconds
  );
  if (years === void 0 && months === void 0 && weeks === void 0 && days === void 0 && hours === void 0 && minutes === void 0 && seconds === void 0 && milliseconds === void 0) {
    throw new Error("Invalid ISO format, no values given");
  }
  return {
    ...years ? { years } : {},
    ...months ? { months } : {},
    ...weeks ? { weeks } : {},
    ...days ? { days } : {},
    ...hours ? { hours } : {},
    ...minutes ? { minutes } : {},
    ...seconds ? { seconds } : {},
    ...milliseconds ? { milliseconds } : {}
  };
}

exports.parseIsoDuration = parseIsoDuration;
exports.parseMsDuration = parseMsDuration;
exports.parseObjectDuration = parseObjectDuration;
exports.propsOfHumanDuration = propsOfHumanDuration;
exports.readDurationFromConfig = readDurationFromConfig;
//# sourceMappingURL=readDurationFromConfig.cjs.js.map
