import { format, offset, parse, removeOffset, tzDate } from '@formkit/tempo';
import {} from '../enums/index.js';
/**
 * From a Date FieldType, return it's equivalent TempoJS format,
 * refer to TempoJS docs for the format tokens being used: https://tempo.formkit.com/#format
 * @param {FieldType} fieldType
 * @param { withZeroPadding: [boolean]; withDefaultIso8601: [boolean]; } [options] -
 *   - withZeroPadding: should we include zero padding in format (e.g.: 03:04:54 instead of 3:4:54)
 *   - withDefaultIso8601: should we use ISO8601 for `date` or `dateIso`
 */
export function mapTempoDateFormatWithFieldType(fieldType, options) {
    let map;
    const withZeroPadding = options?.withZeroPadding ?? false;
    switch (fieldType) {
        case 'dateTime':
        case 'dateTimeIso':
            map = 'YYYY-MM-DD HH:mm:ss';
            break;
        case 'dateTimeIsoAmPm':
            map = 'YYYY-MM-DD hh:mm:ss a';
            break;
        case 'dateTimeIsoAM_PM':
            map = 'YYYY-MM-DD hh:mm:ss A';
            break;
        case 'dateTimeShortIso':
            map = 'YYYY-MM-DD HH:mm';
            break;
        // all Euro Formats (date/month/year)
        case 'dateEuro':
            map = 'DD/MM/YYYY';
            break;
        case 'dateEuroShort':
            map = withZeroPadding ? 'DD/MM/YY' : 'D/M/YY';
            break;
        case 'dateTimeEuro':
            map = 'DD/MM/YYYY HH:mm:ss';
            break;
        case 'dateTimeShortEuro':
            map = withZeroPadding ? 'DD/MM/YYYY HH:mm' : 'D/M/YYYY H:m';
            break;
        case 'dateTimeEuroAmPm':
            map = 'DD/MM/YYYY hh:mm:ss a';
            break;
        case 'dateTimeEuroAM_PM':
            map = 'DD/MM/YYYY hh:mm:ss A';
            break;
        case 'dateTimeEuroShort':
            map = withZeroPadding ? 'DD/MM/YY HH:mm:ss' : 'D/M/YY H:m:s';
            break;
        case 'dateTimeEuroShortAmPm':
            map = withZeroPadding ? 'DD/MM/YY hh:mm:ss a' : 'D/M/YY h:m:s a';
            break;
        case 'dateTimeEuroShortAM_PM':
            map = withZeroPadding ? 'DD/MM/YY hh:mm:ss A' : 'D/M/YY h:m:s A';
            break;
        // all US Formats (month/date/year)
        case 'dateUs':
            map = 'MM/DD/YYYY';
            break;
        case 'dateUsShort':
            map = withZeroPadding ? 'MM/DD/YY' : 'M/D/YY';
            break;
        case 'dateTimeUs':
            map = 'MM/DD/YYYY HH:mm:ss';
            break;
        case 'dateTimeUsAmPm':
            map = 'MM/DD/YYYY hh:mm:ss a';
            break;
        case 'dateTimeUsAM_PM':
            map = 'MM/DD/YYYY hh:mm:ss A';
            break;
        case 'dateTimeUsShort':
            map = withZeroPadding ? 'MM/DD/YY HH:mm:ss' : 'M/D/YY H:m:s';
            break;
        case 'dateTimeUsShortAmPm':
            map = withZeroPadding ? 'MM/DD/YY hh:mm:ss a' : 'M/D/YY h:m:s a';
            break;
        case 'dateTimeUsShortAM_PM':
            map = withZeroPadding ? 'MM/DD/YY hh:mm:ss A' : 'M/D/YY h:m:s A';
            break;
        case 'dateTimeShortUs':
            map = withZeroPadding ? 'MM/DD/YYYY HH:mm' : 'M/D/YYYY H:m';
            break;
        case 'dateUtc':
            map = 'ISO8601';
            break;
        case 'date':
        case 'dateIso':
        default:
            map = options?.withDefaultIso8601 ? 'ISO8601' : 'YYYY-MM-DD';
            break;
    }
    return map;
}
/**
 * Format a date using Tempo and a defined input/output field types
 * @param {string|Date} inputDate
 * @param {FieldType} inputFieldType
 * @param {FieldType} outputFieldType
 * @returns
 */
export function formatDateByFieldType(inputDate, inputFieldType, outputFieldType) {
    const inputFormat = inputFieldType ? mapTempoDateFormatWithFieldType(inputFieldType) : undefined;
    const outputFormat = mapTempoDateFormatWithFieldType(outputFieldType);
    const date = inputDate instanceof Date ? inputDate : tryParseDate(inputDate, inputFormat);
    if (date && inputDate !== undefined) {
        if (outputFieldType === 'dateUtc') {
            return date.toISOString();
        }
        return format(date, outputFormat, 'en-US');
    }
    return '';
}
/**
 * Try to parse date with Tempo or return `false` (instead of throwing) if Date is invalid.
 * When using strict mode, it will detect if the date is invalid when outside of the calendar (e.g. "2011-11-31").
 * However in non-strict mode, it will roll the date backward if out of calendar (e.g. "2011-11-31" would return "2011-11-30").
 * @param {string|Date} [inputDate] - input date (or null)
 * @param {string} [inputFormat] - optional input format to use when parsing
 * @param {Boolean} [strict] - are we using strict mode?
 * @returns
 */
export function tryParseDate(inputDate, inputFormat, strict = false) {
    try {
        if (!inputDate) {
            return false;
        }
        const d = inputDate instanceof Date
            ? inputDate
            : parse({
                date: inputDate,
                format: inputFormat,
                dateOverflow: strict ? 'throw' : 'backward',
                locale: 'en-US',
            });
        // make sure we have a valid year before returning, otherwise return false
        // e.g blank date "0001-01-01" will throw with Tempo `format()`, so better return false
        return d.getFullYear() > 1000 ? d : false;
    }
    catch (_e) {
        return false;
    }
}
/**
 * Parse a Date as a UTC date (without local TZ offset)
 * @param inputDate
 * @returns
 */
export function toUtcDate(inputDate) {
    // to parse as UTC in Tempo, we need to remove the offset (which is a simple inversed offset to cancel itself)
    return removeOffset(inputDate, offset(inputDate, 'utc'));
}
/**
 * Parse a date passed as a string (Date only, without time) and return a TZ Date (without milliseconds)
 * @param inputDateString
 * @returns TZ UTC date formatted
 */
export function parseUtcDate(inputDateString) {
    let outputFormattedDate = '';
    if (typeof inputDateString === 'string' && /^[0-9\-/]*$/.test(inputDateString)) {
        // get the UTC datetime but make sure to decode the value so that it's valid text
        const dateString = decodeURIComponent(inputDateString);
        const date = tzDate(dateString, 'utc');
        if (date) {
            outputFormattedDate = date.toISOString().replace(/(.*)([.\d]{4})(Z)/gi, '$1$3');
        }
    }
    return outputFormattedDate;
}
//# sourceMappingURL=dateUtils.js.map