import { coerceBoolean } from '@angular-ru/cdk/coercion';

function $any(value) {
    return value;
}

function $cast(value) {
    return value;
}

function checkValueIsEmpty(value) {
    // note: don't use isString for preserve circular dependencies
    const nextValue = typeof value === 'string' ? value.trim() : value;
    return [undefined, null, NaN, '', Infinity].includes(nextValue);
}

function checkEveryValueIsEmpty(...values) {
    return values.every((element) => checkValueIsEmpty(element));
}

function isFalse(value) {
    return value === false;
}

function checkEveryValueIsFalse(...values) {
    return values.length === 0 ? false : values.every((element) => isFalse(element));
}

function checkValueIsFilled(value) {
    return !checkValueIsEmpty(value);
}

function checkEveryValueIsFilled(...values) {
    return values.every((element) => checkValueIsFilled(element));
}

function isTrue(value) {
    return value === true;
}

function checkEveryValueIsTrue(...values) {
    return values.length === 0 ? false : values.every((element) => isTrue(element));
}

function checkSomeValueIsEmpty(...values) {
    return values.some((element) => checkValueIsEmpty(element));
}

function checkSomeValueIsFalse(...values) {
    return values.some((element) => isFalse(element));
}

function checkSomeValueIsTrue(...values) {
    return values.some((element) => isTrue(element));
}

function isNil(value) {
    return value === null || typeof value === 'undefined';
}

function isNotNil(value) {
    return !isNil(value);
}

// eslint-disable-next-line max-lines-per-function
function copyHtml(plainHtml) {
    const element = document.createElement('div');
    element.innerHTML = plainHtml;
    element.style.position = 'absolute';
    element.style.opacity = '0';
    element.style.pointerEvents = 'none';
    document.body.appendChild(element);
    const range = document.createRange();
    range.selectNode(element);
    const selection = window.getSelection();
    if (isNil(selection)) {
        throw new Error('Selection is not supported by this browser');
    }
    const previousRange = selection.rangeCount > 0 ? selection.getRangeAt(0) : null;
    selection.removeAllRanges();
    selection.addRange(range);
    // eslint-disable-next-line deprecation/deprecation
    document.execCommand('copy');
    document.body.removeChild(element);
    if (isNotNil(previousRange)) {
        selection.removeAllRanges();
        selection.addRange(previousRange);
    }
}

/**
 * @deprecated Use `copyString`
 */
const copyBuffer = copyString;
function copyString(str) {
    const firstIndex = 0;
    const element = document.createElement('textarea');
    element.value = str;
    element.setAttribute('readonly', '');
    element.style.position = 'absolute';
    element.style.left = '-9999px';
    document.body.appendChild(element);
    const selected = document?.getSelection()?.rangeCount > firstIndex ? document?.getSelection().getRangeAt(firstIndex) : false;
    element.select();
    document.execCommand('copy');
    document.body.removeChild(element);
    if (coerceBoolean(selected)) {
        document?.getSelection()?.removeAllRanges();
        document?.getSelection()?.addRange(selected);
    }
}

const associative = {
    unitIndex: 0,
    pairIndex: 1,
    multipleIndex: 2
};
/**
 * @description: We pass this function a number, and an array of headers,
 * among which the correct form will be chosen to match the number.
 * The first element of the directory is for units, the second is for pairs,
 * and the third is for other numbers.
 *
 *
 * The declination depends on the last digit of the number.
 * Second: 1.
 * Seconds: 0, 5, 6, 7, 8, 9.
 * Seconds: 2, 3, 4.
 *
 * Given the ranges used, the last digit can be obtained as a remainder of division by 10.
 *
 * @param numberValue example as 1
 * @param dictionary example as ["арбуз", "арбуза", "арбузов"]
 * @return Nullable<string> as "арбуз"
 */
function declinationOfNumber(numberValue, dictionary) {
    const remainder = Math.abs(numberValue) % 100;
    let result;
    if (isMultipleDeclination(remainder)) {
        result = dictionary[associative.multipleIndex];
    }
    else if (isPairDeclination(remainder)) {
        result = dictionary[associative.pairIndex];
    }
    else if (isUnitDeclination(remainder)) {
        result = dictionary[associative.unitIndex];
    }
    else {
        result = dictionary[associative.multipleIndex];
    }
    return result;
}
function isMultipleDeclination(remainder) {
    return remainder > 10 && remainder < 20;
}
function isPairDeclination(remainder) {
    return remainder % 10 > 1 && remainder % 10 < 5;
}
function isUnitDeclination(remainder) {
    return remainder % 10 === 1;
}

function detectChanges(detectorOrDetectors) {
    if (isNil(detectorOrDetectors)) {
        return;
    }
    if (Array.isArray(detectorOrDetectors)) {
        for (const detector of detectorOrDetectors) {
            internalDetectChanges(detector);
        }
    }
    else if (isNotNil(detectorOrDetectors)) {
        internalDetectChanges(detectorOrDetectors);
    }
}
function internalDetectChanges(cd) {
    if (isNotNil(cd) && !cd.destroyed) {
        cd.detectChanges();
    }
}

function downloadFile(file) {
    if (checkEveryValueIsEmpty(file.name, file.extension)) {
        throw new Error('File name or file extension must be provided');
    }
    const anchor = document.createElement('a');
    const url = window.URL.createObjectURL(file.blob);
    const filePath = [file.name, file.extension].filter(Boolean).join('.');
    anchor.href = url;
    anchor.download = filePath;
    anchor.click();
    window.URL.revokeObjectURL(url);
}

function fallbackIfEmpty(value, fallback) {
    return (checkValueIsEmpty(value) ? fallback : value);
}

/* eslint-disable @typescript-eslint/no-magic-numbers */
function generateUid() {
    // eslint-disable-next-line spellcheck/spell-checker
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
        const r = (Math.random() * 16) | 0;
        const v = c === 'x' ? r : (r & 0x3) | 0x8;
        return v.toString(16);
    });
}

function getBodyRect() {
    return document.querySelector('body')?.getBoundingClientRect();
}

function isBoolean(value) {
    return typeof value === 'boolean';
}

function isTruthy(value) {
    return Boolean(value);
}

function isFalsy(value) {
    return !isTruthy(value);
}

function isIE(userAgent = navigator.userAgent) {
    return /edge|msie\s|trident\//i.test(userAgent);
}

function parseXmlFromString(xml, type = 'application/xml') {
    const parser = new DOMParser();
    const dom = parser.parseFromString(xml, type);
    if (dom.documentElement.nodeName === 'parsererror') {
        console.error(dom);
        throw new Error('error while parsing');
    }
    return dom;
}

const DEFAULT_UNITS_MAP = {
    s: 1,
    m: 60,
    h: 3600,
    d: 86400,
    w: 604800
};

const NUMBER_PATTERN = `([0-9]+([\.][0-9]+)?)`;
function replaceUnits(text, unitsMap) {
    return parseMultiLineText(text, unitsMap);
}
function parseMultiLineText(text, unitsMap) {
    const textList = [];
    for (const item of text.split('\n')) {
        let prepared = item;
        prepared = replaceMultiple(prepared, unitsMap);
        prepared = replaceSingle(prepared, unitsMap);
        textList.push(prepared);
    }
    return textList.join('\n');
}
function replaceMultiple(value, unitsMap) {
    const pattern = getMultipleUnitsPattern(unitsMap);
    let text = value;
    while (pattern.test(text)) {
        text = replaceByMatch(text, pattern, unitsMap);
    }
    return text;
}
function replaceSingle(value, unitsMap) {
    const pattern = getSingleUnitPattern(unitsMap);
    let text = value;
    while (pattern.test(text)) {
        text = replaceByMatch(text, pattern, unitsMap);
    }
    return text;
}
function replaceByMatch(text, pattern, unitsMap) {
    const match = pattern.exec(text)?.[0] ?? '';
    const num = convertToNumber(match, unitsMap);
    const prepared = match.replace(new RegExp(/\S.*\S/), num.toString());
    return text.replace(pattern, prepared);
}
function convertToNumber(text, unitsMap) {
    const units = text.trim();
    const sum = units
        .split(' ')
        .filter((item) => item !== '')
        .map((item) => {
        const coefficient = getCoefficient(item);
        const unitValue = getUnitValue(item, unitsMap);
        return coefficient * unitValue;
    })
        .reduce((accumulator, item) => accumulator + item, 0);
    return sum;
}
function getMultipleUnitsPattern(unitsMap) {
    const unitKeys = getUnitKeys(unitsMap);
    return new RegExp(`(^|\\s)((${NUMBER_PATTERN})(${unitKeys}))(\\s+((${NUMBER_PATTERN})(${unitKeys})))+(\\s|$)`);
}
function getSingleUnitPattern(unitsMap) {
    const unitKeys = getUnitKeys(unitsMap);
    return new RegExp(`(^|\\s)(${NUMBER_PATTERN})(${unitKeys})(\\s|$)`);
}
function getCoefficient(unit) {
    const prefix = unit.match(`^${NUMBER_PATTERN}`)?.[0] ?? '';
    const result = prefix.includes('.') ? parseFloat(prefix) : parseInt(prefix);
    return result;
}
function getUnitValue(unit, unitsMap) {
    const postfix = unit.match(/\D+$/s)?.[0] ?? '';
    return unitsMap[postfix] ?? 0;
}
function getUnitKeys(unitsMap) {
    return Object.keys(unitsMap)
        .map((item) => (item.length > 1 ? `(${item})` : item))
        .join('|');
}

function serializeXmlToString(xml) {
    return new XMLSerializer().serializeToString(xml);
}

function tryParseJson(text) {
    try {
        return JSON.parse(text);
    }
    catch {
        return undefined;
    }
}

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

export { $any, $cast, DEFAULT_UNITS_MAP, checkEveryValueIsEmpty, checkEveryValueIsFalse, checkEveryValueIsFilled, checkEveryValueIsTrue, checkSomeValueIsEmpty, checkSomeValueIsFalse, checkSomeValueIsTrue, checkValueIsEmpty, checkValueIsFilled, copyBuffer, copyHtml, copyString, declinationOfNumber, detectChanges, downloadFile, fallbackIfEmpty, generateUid, getBodyRect, isBoolean, isFalse, isFalsy, isIE, isNil, isNotNil, isTrue, isTruthy, parseXmlFromString, replaceUnits, serializeXmlToString, tryParseJson };
//# sourceMappingURL=angular-ru-cdk-utils.mjs.map
