import { asNumber, findElementFromEventPath, first, isString, last, modulo, } from '../common/util.js';
import { CalendarDay, daysInWeek, toCalendarDay, } from './model.js';
import { DateRangeType, } from './types.js';
export const MONTHS_PER_ROW = 3;
export const YEARS_PER_ROW = 3;
export const YEARS_PER_PAGE = 15;
const DaysMap = {
    sunday: 0,
    monday: 1,
    tuesday: 2,
    wednesday: 3,
    thursday: 4,
    friday: 5,
    saturday: 6,
};
export function isValidDate(date) {
    return Number.isNaN(date.valueOf()) ? null : date;
}
export function parseISODate(string) {
    if (/^\d{4}/.test(string)) {
        const time = !string.includes('T') ? 'T00:00:00' : '';
        return isValidDate(new Date(`${string}${time}`));
    }
    if (/^\d{2}/.test(string)) {
        const date = first(new Date().toISOString().split('T'));
        return isValidDate(new Date(`${date}T${string}`));
    }
    return null;
}
export function convertToDate(value) {
    if (!value) {
        return null;
    }
    return isString(value) ? parseISODate(value) : isValidDate(value);
}
export function getDateFormValue(value) {
    return value ? value.toISOString() : null;
}
export function convertToDates(value) {
    if (!value) {
        return null;
    }
    const values = [];
    const iterator = isString(value) ? value.split(',') : value;
    for (const each of iterator) {
        const date = convertToDate(isString(each) ? each.trim() : each);
        if (date) {
            values.push(date);
        }
    }
    return values;
}
export function getViewElement(event) {
    const element = findElementFromEventPath('[data-value]', event);
    return element ? asNumber(element.dataset.value, -1) : -1;
}
export function getWeekDayNumber(value) {
    return DaysMap[value];
}
export function areSameMonth(first, second) {
    const [a, b] = [toCalendarDay(first), toCalendarDay(second)];
    return a.year === b.year && a.month === b.month;
}
export function isNextMonth(target, origin) {
    const [a, b] = [toCalendarDay(target), toCalendarDay(origin)];
    return a.year === b.year ? a.month > b.month : a.year > b.year;
}
export function isPreviousMonth(target, origin) {
    const [a, b] = [toCalendarDay(target), toCalendarDay(origin)];
    return a.year === b.year ? a.month < b.month : a.year < b.year;
}
export function* calendarRange(options) {
    let low = toCalendarDay(options.start);
    const unit = options.unit ?? 'day';
    const high = typeof options.end === 'number'
        ? low.add(unit, options.end)
        : toCalendarDay(options.end);
    const reverse = high.lessThan(low);
    const step = reverse ? -1 : 1;
    while (!reverse ? low.lessThan(high) : low.greaterThan(high)) {
        yield low;
        low = low.add(unit, step);
    }
}
export function* generateMonth(value, firstWeekDay) {
    const { year, month } = toCalendarDay(value);
    const start = new CalendarDay({ year, month });
    const offset = modulo(start.day - firstWeekDay, daysInWeek);
    yield* calendarRange({
        start: start.add('day', -offset),
        end: 42,
    });
}
export function getYearRange(current, range) {
    const year = toCalendarDay(current).year;
    const start = Math.floor(year / range) * range;
    return { start, end: start + range - 1 };
}
export function isDateInRanges(date, ranges) {
    const value = toCalendarDay(date);
    return ranges.some((range) => {
        const days = (range.dateRange ?? []).map((day) => toCalendarDay(day));
        switch (range.type) {
            case DateRangeType.After:
                return value.greaterThan(first(days));
            case DateRangeType.Before:
                return value.lessThan(first(days));
            case DateRangeType.Between: {
                const min = Math.min(first(days).timestamp, last(days).timestamp);
                const max = Math.max(first(days).timestamp, last(days).timestamp);
                return value.timestamp >= min && value.timestamp <= max;
            }
            case DateRangeType.Specific:
                return days.some((day) => day.equalTo(value));
            case DateRangeType.Weekdays:
                return !value.weekend;
            case DateRangeType.Weekends:
                return value.weekend;
            default:
                return false;
        }
    });
}
//# sourceMappingURL=helpers.js.map