"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.convertStringToMoment = convertStringToMoment;
exports.customizeCalendarView = customizeCalendarView;
exports.customizeRenderCalendarView = customizeRenderCalendarView;
exports.getDateTimeFormat = getDateTimeFormat;
exports.getLeftCalendarInitialView = getLeftCalendarInitialView;
exports.getRightCalendarInitialView = getRightCalendarInitialView;
exports.getValidityFromErrors = getValidityFromErrors;
exports.isMonthRelatedToTimePicker = isMonthRelatedToTimePicker;
exports.isNavigationAvailableForMonthsView = isNavigationAvailableForMonthsView;
exports.isNavigationAvailableForYearsView = isNavigationAvailableForYearsView;
exports.isValidDateTime = isValidDateTime;
exports.truncateDateTimeToFormat = truncateDateTimeToFormat;
exports.useGetDateTimeValidityError = useGetDateTimeValidityError;
exports.useValidateOnClick = useValidateOnClick;
var _react = _interopRequireDefault(require("react"));
var _moment = _interopRequireDefault(require("moment"));
var _isEmpty = _interopRequireDefault(require("lodash-es/isEmpty"));
var _omit = _interopRequireDefault(require("lodash-es/omit"));
var _formField = require("../form-field");
var _message = require("../message");
var _button = require("../button");
var _datetimeRangePicker = require("./datetime-range-picker");
var _useTranslation = require("../hooks/use-translation");
var _datetimeRangePickerPanel = require("./datetime-range-picker-panel");
var _jsxRuntime = require("react/jsx-runtime");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const DEFAULT_DATETIME_FORMAT = 'YYYY-MM-DDTHH:mm:ss.SSSSSSZ';
const VALIDATION_ENTITY = {
  days: {
    start: 'Start Date',
    end: 'End Date'
  },
  months: {
    start: 'Start Month',
    end: 'End Month'
  }
};
function useValidateOnClick() {
  const {
    t
  } = (0, _useTranslation.useTranslation)();
  return function validateOnClick({
    start,
    end,
    minStart,
    maxEnd,
    viewMode,
    dateTimeFormat,
    sameDateError
  }) {
    const [minStartTrimmed, maxEndTrimmed] = [minStart, maxEnd].map(datetime => datetime ? truncateDateTimeToFormat(datetime, dateTimeFormat) : null);
    const startErrors = {};
    let endErrors = {};
    if (minStartTrimmed && start?.isBefore(minStartTrimmed)) {
      startErrors[_datetimeRangePickerPanel.DATE_RANGE_ERROR_TYPES.START_BEFORE_MIN] = t('{{fieldName}} cannot be before {{date}}.', {
        fieldName: VALIDATION_ENTITY[viewMode].start,
        date: minStartTrimmed.format(dateTimeFormat)
      });
    }
    if (maxEndTrimmed && start?.isAfter(maxEndTrimmed)) {
      startErrors[_datetimeRangePickerPanel.DATE_RANGE_ERROR_TYPES.START_AFTER_MAX] = t('{{fieldName}} cannot be after {{date}}.', {
        fieldName: VALIDATION_ENTITY[viewMode].start,
        date: maxEndTrimmed.format(dateTimeFormat)
      });
    }
    if (maxEndTrimmed && end?.isAfter(maxEndTrimmed)) {
      endErrors[_datetimeRangePickerPanel.DATE_RANGE_ERROR_TYPES.END_AFTER_MAX] = t('{{fieldName}} cannot be after {{date}}.', {
        fieldName: VALIDATION_ENTITY[viewMode].end,
        date: maxEndTrimmed.format(dateTimeFormat)
      });
    }
    if (minStartTrimmed && end?.isBefore(minStartTrimmed)) {
      endErrors[_datetimeRangePickerPanel.DATE_RANGE_ERROR_TYPES.END_AFTER_MIN] = t('{{fieldName}} cannot be before {{date}}.', {
        fieldName: VALIDATION_ENTITY[viewMode].end,
        date: minStartTrimmed.format(dateTimeFormat)
      });
    }
    if (!start?.isValid()) {
      startErrors[_datetimeRangePickerPanel.DATE_RANGE_ERROR_TYPES.INVALID_START_DATE] = t('You need to set {{fieldName}}', {
        fieldName: VALIDATION_ENTITY[viewMode].start
      });
    }
    if (!end?.isValid()) {
      endErrors[_datetimeRangePickerPanel.DATE_RANGE_ERROR_TYPES.INVALID_END_DATE] = t('You need to set {{fieldName}}', {
        fieldName: VALIDATION_ENTITY[viewMode].end
      });
    }
    if (start && !end?.isValid()) {
      endErrors[_datetimeRangePickerPanel.DATE_RANGE_ERROR_TYPES.INVALID_END_DATE] = t('You need to set {{fieldName}}', {
        fieldName: VALIDATION_ENTITY[viewMode].end
      });
    }
    if (start && end && end.isValid()) {
      endErrors = (0, _omit.default)(endErrors, [_datetimeRangePickerPanel.DATE_RANGE_ERROR_TYPES.INVALID_END_DATE]);
    }
    if (sameDateError && start?.isSame(end)) {
      startErrors[_datetimeRangePickerPanel.DATE_RANGE_ERROR_TYPES.START_END_SAME] = t('{{startField}} and {{endField}} cannot be the same', {
        startField: VALIDATION_ENTITY[viewMode].start,
        endField: VALIDATION_ENTITY[viewMode].end
      });
    }
    return {
      startErrors,
      endErrors
    };
  };
}

/** Checks whether a string can be strictly parsed as a moment object following a provided datetime format
 *
 * @param {string} proposedDateTime
 * @param {string} dateTimeFormat
 * @returns {boolean}
 */
function isValidDateTime(proposedDateTime, dateTimeFormat) {
  try {
    convertStringToMoment(proposedDateTime, {
      dateTimeFormat
    })?.isValid();
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
  } catch (err) {
    return false;
  }
  return true;
}
function useGetDateTimeValidityError() {
  const {
    t
  } = (0, _useTranslation.useTranslation)();
  return function getDateTimeValidityError(dateTime, dateTimeFormat) {
    if (_moment.default.isMoment(dateTime)) {
      return;
    }
    if (typeof dateTime === 'string') {
      if (isValidDateTime(dateTime, dateTimeFormat)) {
        return;
      }
      return t('Must follow {{dateTimeFormat}} format', {
        dateTimeFormat
      });
    }
    return t('Expected a datetime');
  };
}
function getValidityFromErrors(errorMapping) {
  let validityValues;
  if ((0, _isEmpty.default)(errorMapping)) {
    validityValues = '';
  } else {
    validityValues = Object.values(errorMapping);
  }
  return {
    type: _message.MESSAGE_TYPES.ERROR,
    value: validityValues,
    displayLocation: _formField.MESSAGE_DISPLAY_LOCATION.SUMMARY
  };
}
function customizeCalendarView(selectedDate, start, end, className, viewMode) {
  let classes = selectedDate.isBetween(start, end, viewMode) ? `${className} in-selecting-range` : className;
  classes = selectedDate.isSame(start, viewMode) || selectedDate.isSame(end, viewMode) ? `${classes} rdtActive` : classes.replace('rdtActive', '');
  return classes;
}
function customizeRenderCalendarView(mode, pickerRef, value, dateTimeFormat, timeFormat, renderDefault) {
  if (mode === 'time') {
    const setDayView = () => pickerRef.current?.setState({
      // We are hacking the Datetime pickers setState function here
      // eslint-disable-next-line @typescript-eslint/ban-ts-comment
      // @ts-ignore
      currentView: 'days'
    });
    return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
      children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_button.Button, {
        testId: "apply-button-time-view",
        className: "apply-button",
        accentType: _button.ACCENT_TYPES.SECONDARY,
        onClick: setDayView,
        children: (0, _moment.default)(value).format(dateTimeFormat)
      }), renderDefault()]
    });
  }
  if (mode === 'days') {
    const setTimeView = () => pickerRef.current?.setState({
      // We are hacking the Datetime pickers setState function here
      // eslint-disable-next-line @typescript-eslint/ban-ts-comment
      // @ts-ignore
      currentView: 'time'
    });
    return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
      children: [renderDefault(), timeFormat && /*#__PURE__*/(0, _jsxRuntime.jsx)(_button.Button, {
        testId: "apply-button-month-view",
        className: "apply-button",
        accentType: _button.ACCENT_TYPES.SECONDARY,
        onClick: setTimeView,
        children: (0, _moment.default)(value).format(timeFormat)
      })]
    });
  }
  return renderDefault();
}
function isNavigationAvailableForMonthsView(currentView, leftPickerRef, rightPickerRef, quantity) {
  const leftPickerViewDate = leftPickerRef?.current?.state?.viewDate;
  const rightPickerViewDate = rightPickerRef?.current?.state?.viewDate;
  const minLeftMonth = (0, _moment.default)(leftPickerViewDate).add(quantity, 'month');
  return currentView === 'months' && minLeftMonth.month() === rightPickerViewDate?.month() && minLeftMonth.year() === rightPickerViewDate?.year();
}
function isNavigationAvailableForYearsView(currentView, leftPickerRef, rightPickerRef, quantity) {
  const leftPickerViewDate = leftPickerRef?.current?.state?.viewDate;
  const rightPickerViewDate = rightPickerRef?.current?.state?.viewDate;
  const minLeftYear = (0, _moment.default)(leftPickerViewDate).add(quantity, 'year');
  return currentView === 'years' && minLeftYear.year() === rightPickerViewDate?.year();
}
function isMonthRelatedToTimePicker(pickerRef, selectedValue) {
  return pickerRef?.current?.state?.currentView === 'time' && pickerRef?.current?.state?.viewDate.isSame(selectedValue, 'month');
}
function getLeftCalendarInitialView(initialDirection, start, end, viewMode) {
  if (start?.isSame(end, viewMode)) {
    return initialDirection === _datetimeRangePicker.INITIAL_DIRECTION.PAST ? (0, _moment.default)(start).subtract(1, viewMode) : (0, _moment.default)(start);
  }
  return (0, _moment.default)(start);
}
function getRightCalendarInitialView(initialDirection, start, end, viewMode) {
  if (start?.isSame(end, viewMode)) {
    return initialDirection === _datetimeRangePicker.INITIAL_DIRECTION.PAST ? (0, _moment.default)(start) : (0, _moment.default)(start).add(1, viewMode);
  }
  return (0, _moment.default)(start).add(1, viewMode);
}

/** Strictly parses a string using a provided datetime format and returns a moment object
 *
 * @param {string|null} datetimeString - A string-representation of a datetime
 * @param {string} [dateTimeFormat=DEFAULT_DATETIME_FORMAT] - The datetime format used to parse the datetime string
 * @param {boolean} [strictParse=true] - If true and the string does not conform to the provided dateFormat,
 *    then an error will be thrown
 * @param {boolean} [allowNil=false] - If false and the string is actually null or undefined, then an error is thrown
 * @returns {moment.Moment|null} - Will return a moment object if the datetime string was successfully parsed as a valid
 *    datetime. May return null if a null datetime-string was passed in and allowNil ===  true.
 */

function convertStringToMoment(datetimeString, {
  dateTimeFormat = DEFAULT_DATETIME_FORMAT,
  strictParse = true,
  allowNil = false
} = {}) {
  if (datetimeString == null) {
    if (allowNil) {
      return null;
    }
    throw Error(`datetime string cannot be null`);
  }
  const dateTime = _moment.default.utc(datetimeString, dateTimeFormat, strictParse);
  if (!dateTime.isValid()) {
    throw Error(`Could not create a valid moment object from ${datetimeString}`);
  }
  return dateTime;
}

/** Takes a moment object and returns a copy, but following the provided datetime format
 *
 * @param {moment.Moment} dateTime
 * @param {string} dateTimeFormat
 * @returns {moment.Moment}
 */
function truncateDateTimeToFormat(dateTime, dateTimeFormat) {
  return convertStringToMoment(dateTime.format(dateTimeFormat), {
    dateTimeFormat
  });
}

/** Takes a date format and a time format (both strings) and returns their concatenation with a space in-between
 *
 * @param {string} dateFormat
 * @param {string} timeFormat
 * @returns {string}
 */
function getDateTimeFormat(dateFormat, timeFormat) {
  if (!timeFormat) {
    return dateFormat;
  }
  if (!dateFormat) {
    return timeFormat;
  }
  return `${dateFormat} ${timeFormat}`;
}