import { isNotNil, checkSomeValueIsEmpty, isNil, checkValueIsFilled } from '@angular-ru/cdk/utils';
import { FormGroup, FormControl } from '@angular/forms';
import { checkIsShallowEmpty, getValueByPath } from '@angular-ru/cdk/object';
import { BigDecimal } from '@angular-ru/cdk/big-decimal';
import { hasNoItems, hasItems } from '@angular-ru/cdk/array';

function assertFormGroup(control, controlName) {
    if (!(control instanceof FormGroup)) {
        throw new Error(`${controlName} must be used on form group`);
    }
}

function getDateInterval(from, to) {
    if (isNotNil(from) && isNotNil(to)) {
        const fromTimestamp = new Date(from).getTime();
        const toTimestamp = new Date(to).getTime();
        return Math.abs(toTimestamp - fromTimestamp);
    }
    else {
        return null;
    }
}

const DATE_INTERVAL_VALIDATOR = 'DateIntervalValidator';
function dateMaxIntervalValidator(intervalLimit, descriptor) {
    return dateIntervalValidator(intervalLimit, descriptor, "maxDateIntervalLimit" /* LIMIT_MAX_INTERVAL */);
}
function dateMinIntervalValidator(intervalLimit, descriptor) {
    return dateIntervalValidator(intervalLimit, descriptor, "minDateIntervalLimit" /* LIMIT_MIN_INTERVAL */);
}
function orderedIntervalValidator({ dateFromKey, dateToKey }) {
    return (formGroup) => {
        assertFormGroup(formGroup, DATE_INTERVAL_VALIDATOR);
        const validatorType = "orderedInterval" /* ORDERED_INTERVAL */;
        const formGroupValue = formGroup.getRawValue();
        const from = formGroupValue[dateFromKey];
        const to = formGroupValue[dateToKey];
        if (checkSomeValueIsEmpty(from, to)) {
            return null;
        }
        return (from ?? 0) > (to ?? 0) ? { [validatorType]: true } : null;
    };
}
function dateIntervalValidator(intervalLimit, { dateFromKey, dateToKey }, type) {
    const intervalLimitTimestamp = new Date(intervalLimit).getTime();
    return (formGroup) => {
        assertFormGroup(formGroup, DATE_INTERVAL_VALIDATOR);
        const formGroupValue = formGroup.getRawValue();
        const interval = getDateInterval(formGroupValue[dateFromKey], formGroupValue[dateToKey]);
        const limitExceeded = isNotNil(interval) &&
            (type === "maxDateIntervalLimit" /* LIMIT_MAX_INTERVAL */
                ? interval > intervalLimitTimestamp
                : interval < intervalLimitTimestamp);
        return limitExceeded ? { [type]: true } : null;
    };
}

/**
 * @deprecated use `requiredSomeValueValidator`
 */
const emptyValidator = (control) => {
    const filterData = control.controls;
    const values = Object.values(filterData);
    const formValues = values.map((element) => element.value?.toString().trim());
    const validFormValues = formValues.filter((value) => value);
    return validFormValues.length === 0 ? { empty: true } : null;
};

function everyArrayItemValidator(validators) {
    return (control) => {
        if (Array.isArray(control.value)) {
            const errors = control.value
                .map((value) => getErrorsForSingleValue(value, validators))
                .reduce((accumulator, element) => concatErrors(accumulator, element), {});
            return checkIsShallowEmpty(errors) ? null : errors;
        }
        return null;
    };
}
function getErrorsForSingleValue(value, validators) {
    const control = new FormControl(value, { validators });
    return control.errors;
}
function concatErrors(accumulator, element) {
    return { ...accumulator, ...element };
}

function maxDateValidator(maxDate) {
    return limitDateValidator(maxDate, "maxDateLimitExceeded" /* LIMIT_MAX_INTERVAL */);
}
function minDateValidator(maxDate) {
    return limitDateValidator(maxDate, "minDateLimitExceeded" /* LIMIT_MIN_INTERVAL */);
}
function limitDateValidator(maxDate, type) {
    const maxDateTimestamp = new Date(maxDate).getTime();
    if (isNaN(maxDateTimestamp)) {
        throw new Error('maxDate value must be correct date');
    }
    return (control) => {
        const dateTimestamp = new Date(control.value).getTime();
        if (isNaN(dateTimestamp)) {
            return null;
        }
        else {
            const limitExceeded = type === "maxDateLimitExceeded" /* LIMIT_MAX_INTERVAL */
                ? dateTimestamp > maxDateTimestamp
                : dateTimestamp < maxDateTimestamp;
            return limitExceeded ? { [type]: true } : null;
        }
    };
}

const MIN_LONG_VALUE = new BigDecimal('-9223372036854775808');
const MAX_LONG_VALUE = new BigDecimal('9223372036854775807');
function longValidator() {
    return (control) => {
        if (isNil(control.value)) {
            return null;
        }
        return isLong(control.value.toString().trim()) ? null : { long: true };
    };
}
function isLong(value) {
    if (isNil(value) || value.toString().match(/[^\d\-]/g)) {
        return false;
    }
    else {
        const decimal = new BigDecimal(value);
        const comparedLeft = decimal.compareTo(MIN_LONG_VALUE);
        const comparedRight = decimal.compareTo(MAX_LONG_VALUE);
        return !((comparedLeft === 1 && comparedRight === 1) || (comparedLeft === -1 && comparedRight === -1));
    }
}

const VALIDATOR_TYPE$1 = 'requiredSomeValueByKeys';
function requiredSomeValueByKeysValidator(keyList = []) {
    return (formGroup) => {
        assertFormGroup(formGroup, VALIDATOR_TYPE$1);
        if (hasNoItems(keyList)) {
            return null;
        }
        const formGroupValue = formGroup.getRawValue();
        let result = { [VALIDATOR_TYPE$1]: true };
        for (const key of keyList) {
            const value = getValueByPath(formGroupValue, key);
            if (formValueIsFilled(value)) {
                result = null;
                break;
            }
        }
        return result;
    };
}
function formValueIsFilled(value) {
    return Array.isArray(value) ? hasItems(value) : checkValueIsFilled(value);
}

const VALIDATOR_TYPE = 'requiredSomeValue';
function requiredSomeValueValidator() {
    return (formGroup) => {
        assertFormGroup(formGroup, VALIDATOR_TYPE);
        const formGroupValue = formGroup.getRawValue();
        const keyList = Object.keys(formGroupValue);
        const error = requiredSomeValueByKeysValidator(keyList)(formGroup);
        return isNil(error) ? null : { [VALIDATOR_TYPE]: true };
    };
}

/**
 * Generated bundle index. Do not edit.
 */

export { dateMaxIntervalValidator, dateMinIntervalValidator, emptyValidator, everyArrayItemValidator, longValidator, maxDateValidator, minDateValidator, orderedIntervalValidator, requiredSomeValueByKeysValidator, requiredSomeValueValidator };
//# sourceMappingURL=angular-ru-cdk-validators.mjs.map
