var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
import { defaultLangCode, langCodesToCanonicalLocale } from '../locale/constants.js';
import { defaultDateComponentsOrder, defaultDateComponentsSeparator, emptyDateComponents } from './constants.js';
import { InternalDateCalculator } from './InternalDateCalculator.js';
import { InternalDateGetter } from './InternalDateGetter.js';
import { InternalDateSetter } from './InternalDateSetter.js';
import { InternalDateTransformer } from './InternalDateTransformer.js';
import { InternalDateValidator } from './InternalDateValidator.js';
import { internalDateLocale } from './localeSets.js';
import { InternalDateComponentType, InternalDateOrder, InternalDateValidateCheck, isInternalDateValidateCheck, } from './types.js';
var getRestoreYear = function (prev, today) {
    if (prev.year !== null && InternalDateValidator.testParseToNumber(prev.year)) {
        var yearNum = Number(prev.year);
        if (yearNum > 50 && yearNum < 100) {
            return yearNum + 1900;
        }
        else if (yearNum > 0 && yearNum < 51) {
            return yearNum + 2000;
        }
        return prev.year;
    }
    return today.year;
};
var InternalDate = /** @class */ (function () {
    function InternalDate(_a) {
        var _b = _a === void 0 ? {} : _a, order = _b.order, separator = _b.separator, _c = _b.langCode, langCode = _c === void 0 ? defaultLangCode : _c, value = _b.value;
        this.components = __assign({}, emptyDateComponents);
        this.canonicalLocale = 'ru-RU';
        this.start = null;
        this.end = null;
        this.order = order !== null && order !== void 0 ? order : internalDateLocale[langCode].order;
        this.separator = separator !== null && separator !== void 0 ? separator : internalDateLocale[langCode].separator;
        this.canonicalLocale = langCodesToCanonicalLocale[langCode];
        if (value !== undefined) {
            this.parseInternalValue(value);
        }
    }
    InternalDate.prototype.getComponentsRaw = function () {
        return __assign({}, this.components);
    };
    InternalDate.prototype.getComponentsLikeNumber = function () {
        return InternalDateTransformer.dateComponentsStringToNumber(this.getComponentsRaw());
    };
    InternalDate.prototype.getSeparator = function () {
        return this.separator;
    };
    InternalDate.prototype.getOrder = function () {
        return this.order;
    };
    InternalDate.prototype.getYear = function () {
        return this.components.year;
    };
    InternalDate.prototype.getMonth = function () {
        return this.components.month;
    };
    InternalDate.prototype.getDate = function () {
        return this.components.date;
    };
    InternalDate.prototype.getRangeStart = function () {
        return this.start;
    };
    InternalDate.prototype.getRangeEnd = function () {
        return this.end;
    };
    InternalDate.prototype.setOrder = function (order) {
        if (order === void 0) { order = defaultDateComponentsOrder; }
        this.order = order;
        return this;
    };
    InternalDate.prototype.setSeparator = function (separator) {
        if (separator === void 0) { separator = defaultDateComponentsSeparator; }
        this.separator = separator;
        return this;
    };
    InternalDate.prototype.setComponents = function (components, isNativeMonth) {
        if (isNativeMonth === void 0) { isNativeMonth = false; }
        if (components && isNativeMonth) {
            var clone = this.clone().setComponents(components).shiftMonth(1);
            if (clone.validate({ checks: [InternalDateValidateCheck.Native] })) {
                this.components = __assign({}, clone.getComponentsLikeNumber());
            }
            return this;
        }
        this.components = components || __assign({}, emptyDateComponents);
        return this;
    };
    InternalDate.prototype.setYear = function (year) {
        this.components.year = year;
        return this;
    };
    InternalDate.prototype.setMonth = function (month) {
        this.components.month = month;
        return this;
    };
    InternalDate.prototype.setDate = function (date) {
        this.components.date = date;
        return this;
    };
    InternalDate.prototype.shiftYear = function (step, _a) {
        var _b = _a === void 0 ? {} : _a, isLoop = _b.isLoop, isRange = _b.isRange, isCutFeb = _b.isCutFeb;
        var min = this.getMinValue(InternalDateComponentType.Year, isRange);
        var max = this.getMaxValue(InternalDateComponentType.Year, { isRange: isRange, isCutFeb: isCutFeb });
        var year = this.getComponentsLikeNumber().year;
        this.components.year = InternalDateCalculator.calcShiftValueDateComponent(step, year, min, max, isLoop);
        return this;
    };
    InternalDate.prototype.shiftMonth = function (step, _a) {
        var _b = _a === void 0 ? {} : _a, isLoop = _b.isLoop, isRange = _b.isRange, isCutFeb = _b.isCutFeb;
        var min = this.getMinValue(InternalDateComponentType.Month, isRange);
        var max = this.getMaxValue(InternalDateComponentType.Month, { isRange: isRange, isCutFeb: isCutFeb });
        var month = this.getComponentsLikeNumber().month;
        this.components.month = InternalDateCalculator.calcShiftValueDateComponent(step, month, min, max, isLoop);
        return this;
    };
    InternalDate.prototype.shiftDate = function (step, _a) {
        var _b = _a === void 0 ? {} : _a, isLoop = _b.isLoop, isRange = _b.isRange, isCutFeb = _b.isCutFeb;
        var min = this.getMinValue(InternalDateComponentType.Date, isRange);
        var max = this.getMaxValue(InternalDateComponentType.Date, { isRange: isRange, isCutFeb: isCutFeb });
        var date = this.getComponentsLikeNumber().date;
        this.components.date = InternalDateCalculator.calcShiftValueDateComponent(step, date, min, max, isLoop);
        return this;
    };
    InternalDate.prototype.setRangeStart = function (internalDate) {
        this.start = internalDate;
        return this;
    };
    InternalDate.prototype.setRangeEnd = function (internalDate) {
        this.end = internalDate;
        return this;
    };
    InternalDate.prototype.get = function (type) {
        return type !== null ? InternalDateGetter.getValueDateComponent(type, this.getComponentsRaw()) : null;
    };
    InternalDate.prototype.set = function (type, value) {
        return type !== null ? InternalDateSetter.setValueDateComponent(this, type, value) : this;
    };
    InternalDate.prototype.shift = function (type, step, settings) {
        return type !== null ? InternalDateSetter.shiftValueDateComponent(this, type, step, settings) : this;
    };
    InternalDate.prototype.parseValue = function (value) {
        if (value === void 0) { value = ''; }
        var components = InternalDateTransformer.parseValueToDate(value, this.order) || __assign({}, emptyDateComponents);
        this.setComponents(components);
        return this;
    };
    InternalDate.prototype.parseInternalValue = function (value) {
        if (value === void 0) { value = ''; }
        var components = InternalDateTransformer.parseValueToDate(value, InternalDateOrder.DMY) || __assign({}, emptyDateComponents);
        this.setComponents(components);
        return this;
    };
    InternalDate.prototype.validate = function (_a) {
        var _b = _a === void 0 ? {} : _a, type = _b.type, nextValue = _b.nextValue, _c = _b.checks, checks = _c === void 0 ? Object.values(InternalDateValidateCheck).filter(isInternalDateValidateCheck) : _c;
        // eslint-disable-next-line @typescript-eslint/no-this-alias
        var self = this;
        if (type !== undefined) {
            var clone = this.clone();
            if (nextValue !== undefined) {
                clone.set(type, nextValue);
            }
            self = clone;
        }
        if (checks.includes(InternalDateValidateCheck.NotNull) &&
            !InternalDateValidator.checkForNull(self.getComponentsRaw(), type)) {
            return false;
        }
        if (checks.includes(InternalDateValidateCheck.Number) &&
            !Object.values(self.getComponentsRaw()).every(InternalDateValidator.testParseToNumber)) {
            return false;
        }
        if (checks.includes(InternalDateValidateCheck.Limits) &&
            !InternalDateValidator.checkLimits(self.getComponentsLikeNumber(), type)) {
            return false;
        }
        if (checks.includes(InternalDateValidateCheck.Native) &&
            !InternalDateValidator.compareWithNativeDate(self.getComponentsLikeNumber())) {
            return false;
        }
        if (checks.includes(InternalDateValidateCheck.Range)) {
            return type !== undefined
                ? InternalDateValidator.checkRangePiecemeal(type, self.getComponentsLikeNumber(), self.start && self.start.getComponentsLikeNumber(), self.end && self.end.getComponentsLikeNumber())
                : InternalDateValidator.checkRangeFully(self.toNumber(), self.start && self.start.toNumber(), self.end && self.end.toNumber());
        }
        return true;
    };
    InternalDate.prototype.toFragments = function (settings, components) {
        if (settings === void 0) { settings = {}; }
        if (components === void 0) { components = this.getComponentsRaw(); }
        return InternalDateTransformer.dateToFragments(components, __assign({ order: this.order, separator: this.separator }, settings));
    };
    /**
     * Перевод даты в числовое представление (**НЕ** аналог `timestamp`)
     * Предназначено для быстрого сравнивания дат `<=>`
     */
    InternalDate.prototype.toNumber = function () {
        return Number(this.toFragments({ order: InternalDateOrder.YMD, withPad: true })
            .map(function (_a) {
            var valueWithPad = _a.valueWithPad;
            return valueWithPad;
        })
            .join(''));
    };
    InternalDate.prototype.toString = function (settings) {
        if (settings === void 0) { settings = {}; }
        return this.toFragments(__assign({ withPad: true, withSeparator: true }, settings))
            .filter(function (_a) {
            var value = _a.value;
            return value !== null;
        })
            .map(function (_a) {
            var type = _a.type, valueWithPad = _a.valueWithPad, value = _a.value;
            return settings.withPad && type !== InternalDateComponentType.Separator ? valueWithPad : value;
        })
            .join('');
    };
    InternalDate.prototype.toInternalString = function () {
        return InternalDateTransformer.dateToInternalString(this.getComponentsRaw());
    };
    InternalDate.prototype.toNativeFormat = function () {
        var components = this.getComponentsLikeNumber();
        if (InternalDateValidator.compareWithNativeDate(components)) {
            return __assign(__assign({}, components), { month: components.month - 1 });
        }
        return undefined;
    };
    InternalDate.prototype.toA11YFormat = function () {
        return InternalDateTransformer.componentsToA11YFormat(this.components, this.canonicalLocale);
    };
    InternalDate.prototype.clone = function () {
        return new InternalDate({ order: this.order, separator: this.separator })
            .setComponents(__assign({}, this.components))
            .setRangeStart(this.start && this.start.clone())
            .setRangeEnd(this.end && this.end.clone());
    };
    InternalDate.prototype.duplicateOf = function (pattern) {
        return this.setComponents(pattern.getComponentsRaw());
    };
    InternalDate.prototype.restore = function (type) {
        if (type === void 0) { type = null; }
        var prev = this.getComponentsRaw();
        var today = InternalDateGetter.getTodayComponents();
        if (prev.year === null && prev.month === null && prev.date === null) {
            return this;
        }
        var restoreYear = getRestoreYear(prev, today);
        if ((type === null && restoreYear !== prev.year) ||
            type === InternalDateComponentType.Year ||
            type === InternalDateComponentType.All) {
            this.setYear(restoreYear);
        }
        if ((type === null && prev.month === null) ||
            type === InternalDateComponentType.Month ||
            type === InternalDateComponentType.All) {
            this.setMonth(today.month);
        }
        if ((type === null && prev.date === null) ||
            type === InternalDateComponentType.Date ||
            type === InternalDateComponentType.All) {
            this.setDate(today.date);
        }
        return this;
    };
    InternalDate.prototype.cutOffExcess = function (type, _a) {
        if (type === void 0) { type = null; }
        var _b = _a === void 0 ? {} : _a, _c = _b.isLoop, isLoop = _c === void 0 ? false : _c, isRange = _b.isRange, _d = _b.isCutFeb, isCutFeb = _d === void 0 ? false : _d;
        var _e = this.components, year = _e.year, month = _e.month, date = _e.date;
        if ((type === null || type === InternalDateComponentType.Year) && InternalDateValidator.testParseToNumber(year)) {
            this.shiftYear(0, { isLoop: isLoop, isRange: isRange, isCutFeb: isCutFeb });
        }
        if ((type === null || type === InternalDateComponentType.Month) && InternalDateValidator.testParseToNumber(month)) {
            this.shiftMonth(0, { isLoop: isLoop, isRange: isRange, isCutFeb: isCutFeb });
        }
        if ((type === null || type === InternalDateComponentType.Date) && InternalDateValidator.testParseToNumber(date)) {
            this.shiftDate(0, { isLoop: isLoop, isRange: isRange, isCutFeb: isCutFeb });
        }
        return this;
    };
    InternalDate.prototype.isIncomplete = function () {
        return !this.isEmpty() && Object.values(this.components).some(function (component) { return component === null; });
    };
    InternalDate.prototype.isEmpty = function () {
        return Object.values(this.components).every(function (component) { return component === null; });
    };
    InternalDate.prototype.isEqualComponentDate = function (type, compared) {
        return this.get(type) === compared.get(type);
    };
    InternalDate.prototype.isEqual = function (compared) {
        return (InternalDateValidator.isEqualDateValues(this, compared) &&
            InternalDateValidator.isEqualDateFormats(this, compared));
    };
    InternalDate.prototype.getMinValue = function (type, isRange) {
        if (isRange === true && this.start !== null) {
            return Number(InternalDateCalculator.calcRangeStartDateComponent(type, this.getComponentsLikeNumber(), this.start.getComponentsLikeNumber()));
        }
        return InternalDateGetter.getDefaultMin(type);
    };
    InternalDate.prototype.getMaxValue = function (type, _a) {
        var _b = _a === void 0 ? {} : _a, isRange = _b.isRange, isCutFeb = _b.isCutFeb;
        if (isRange && this.end !== null) {
            return Number(InternalDateCalculator.calcRangeEndDateComponent(type, this.getComponentsLikeNumber(), this.end.getComponentsLikeNumber()));
        }
        if (!isCutFeb) {
            return InternalDateGetter.getDefaultMax(type);
        }
        return InternalDateGetter.getDefaultMax(type, this.getComponentsLikeNumber());
    };
    return InternalDate;
}());
export { InternalDate };
//# sourceMappingURL=InternalDate.js.map