import { parseToHsl, lighten, readableColor as polishedReadableColor, darken, getContrast, hsl, modularScale, stripUnit, math, getValueAndUnit, transparentize, parseToRgb } from 'polished';
import { tryCatch } from '../utils';
import { wcagContrast } from './constants';
export const backgroundCompatibleColors = (colors, backgroundColor, { level = 'AA' } = {}) => colors.filter(color => getContrast(color, backgroundColor) >=
    (typeof level === 'string' ? wcagContrast[level] : level));
export const supplementalColors = (theme) => Object.values(theme.base.palette['supplemental-colors']);
export const supplementalColorMapping = {
    'Supplemental Color 1': 'color-1',
    'Supplemental Color 2': 'color-2',
    'Supplemental Color 3': 'color-3',
    'Supplemental Color 4': 'color-4',
    'Supplemental Color 5': 'color-5',
    'Supplemental Color 6': 'color-6',
    'Supplemental Color 7': 'color-7',
    'Supplemental Color 8': 'color-8'
};
const isSupplementalColorKey = (key) => key in supplementalColorMapping;
export const resolveSupplementalColor = (theme, key) => {
    if (isSupplementalColorKey(key)) {
        return theme.base.palette['supplemental-colors'][supplementalColorMapping[key]];
    }
};
export const infiniteSupplementalColors = (theme, index) => {
    const base = supplementalColors(theme);
    const baseCount = base.length;
    const colorIndex = index % baseCount;
    const wrapAround = 4;
    const decade = Math.floor(index / baseCount) % wrapAround;
    const baseColor = base[colorIndex];
    if (decade === 0)
        return baseColor;
    const isLighter = decade % 2 === 1;
    const shiftAmount = Math.min(Math.ceil(decade / 2) * 0.1, 0.2);
    return isLighter ? lighten(shiftAmount, baseColor) : darken(shiftAmount, baseColor);
};
export const isSolidColor = (background) => {
    const rgb = tryCatch(() => parseToRgb(background));
    return (rgb &&
        (rgb.alpha === undefined ||
            (rgb.alpha !== undefined && rgb.alpha === 1)));
};
export const readableColor = (color, { mode = 'light', level = 'AA' } = {}) => {
    if (!isSolidColor(color) && mode === 'light') {
        return '#fff';
    }
    if (!isSolidColor(color) && mode === 'dark') {
        return '#000';
    }
    const minContrast = typeof level === 'string' ? wcagContrast[level] : level;
    if (mode === 'light' && getContrast('#fff', color) >= minContrast) {
        return '#fff';
    }
    if (mode === 'dark' && getContrast('#000', color) >= minContrast) {
        return '#000';
    }
    return tryCatch(() => polishedReadableColor(color), () => '#000');
};
const getBackgroundForegroundColors = (color, delta) => {
    const backgroundLightness = tryCatch(() => parseToHsl(color).lightness, () => 1);
    let background = tryCatch(() => lighten(delta, color));
    let foreground = tryCatch(() => readableColor(lighten(delta, color)));
    if (backgroundLightness > 0.35) {
        background = tryCatch(() => darken(delta, color));
        foreground = tryCatch(() => readableColor(darken(delta, color)));
    }
    return { background, foreground };
};
export const getHoverColors = (color) => {
    return getBackgroundForegroundColors(color, 0.1);
};
export const getActiveColors = (color) => {
    return getBackgroundForegroundColors(color, 0.2);
};
export const readableHue = (color1, color2, { mode = 'both', level = 'AA' } = {}) => {
    // if both the color are not solid, return black as fallback
    if (!isSolidColor(color1) && !isSolidColor(color2)) {
        return '#000000';
    }
    // if one of the color is not solid, return the other color
    if (!isSolidColor(color2)) {
        return color1;
    }
    if (!isSolidColor(color1)) {
        return color2;
    }
    const minContrast = typeof level === 'string' ? wcagContrast[level] : level;
    if (getContrast(color1, color2) >= minContrast)
        return color1;
    const { lightness, ...hueSaturation } = parseToHsl(color1);
    let shouldLighten = true;
    let shouldDarken = true;
    let lightEnough = '';
    let darkEnough = '';
    for (let i = 0; i <= 1; i += 0.01) {
        if (shouldLighten) {
            const lightented = hsl({
                ...hueSaturation,
                lightness: Math.min(lightness + i, 1)
            });
            if (getContrast(lightented, color2) >= minContrast) {
                if (mode !== 'dark')
                    return lightented;
                shouldLighten = false;
                lightEnough = lightented;
            }
            if (lightness + i >= 1)
                shouldLighten = false;
        }
        if (shouldDarken) {
            const darkened = hsl({
                ...hueSaturation,
                lightness: Math.max(lightness - i, 0)
            });
            if (getContrast(darkened, color2) >= minContrast) {
                if (mode !== 'light')
                    return darkened;
                shouldDarken = false;
                darkEnough = darkened;
            }
            if (lightness - i <= 0)
                shouldDarken = false;
        }
        if (!shouldLighten && !shouldDarken)
            break;
    }
    if (lightEnough)
        return lightEnough;
    if (darkEnough)
        return darkEnough;
    return readableColor(color2, { mode, level });
};
export const getReadableStatusColor = (theme, status) => {
    const statusColor = theme.components['form-field'][status]['status-color'];
    const backgroundColor = theme.base.palette['primary-background'];
    return tryCatch(() => readableHue(statusColor, backgroundColor), () => statusColor);
};
export const omitProps = (...props) => ({
    shouldForwardProp: prop => !props.includes(prop)
});
const stepsMap = {
    xxs: -2,
    xs: -1,
    s: 0,
    m: 1,
    l: 2,
    xl: 3,
    xxl: 4
};
export const colorIconMapping = (theme, iconName) => {
    switch (iconName) {
        case 'polaris':
        case 'polaris-solid':
            return theme.base.palette.ai;
        case 'paper-clip':
            return theme.base.palette['supplemental-colors']['color-1'];
        case 'user-star':
            return theme.base.palette['supplemental-colors']['color-2'];
        case 'person':
            return theme.base.palette['supplemental-colors']['color-3'];
        case 'tag':
            return theme.base.palette['supplemental-colors']['color-4'];
        case 'folder-nested':
            return theme.base.palette['supplemental-colors']['color-5'];
        default:
            return theme.base.colors.gray.medium;
    }
};
export const calculateFontSize = (baseFontSize, baseFontScale) => {
    return Object.fromEntries(Object.entries(stepsMap).map(([size, steps]) => {
        const calculation = tryCatch(() => baseFontScale === 'linear'
            ? math(`${baseFontSize} + (${steps} * 0.0625rem)`)
            : modularScale(steps, baseFontSize, baseFontScale), () => baseFontSize);
        if (size === 'xs' && Number.parseFloat(`${stripUnit(calculation)}`) < 0.75) {
            return [size, `max(calc((${baseFontSize} + 12px) / 2), 12px)`];
        }
        return [size, `max(${calculation}, 12px)`];
    }));
};
export const calculateForegroundColor = (background, foregroundColor) => {
    if (foregroundColor !== 'auto') {
        return foregroundColor;
    }
    return isSolidColor(background) ? readableColor(background) : '#000000';
};
export const calculateBackgroundAndContrastColor = (background, foregroundColor) => {
    const isGradientBackground = !isSolidColor(background);
    const computedFgColor = calculateForegroundColor(background, foregroundColor);
    const computedBgColor = isGradientBackground ? readableColor(computedFgColor) : background;
    let contrastColor = darken(0.05, computedBgColor);
    if (getContrast(computedBgColor, contrastColor) === 1) {
        contrastColor = lighten(0.15, computedBgColor);
    }
    if (isGradientBackground) {
        contrastColor = transparentize(0.9, computedFgColor);
    }
    return {
        contrastColor,
        backgroundColor: computedBgColor
    };
};
export const getTranslucentColor = (color) => {
    const fallbackColor = isSolidColor(color) ? color : '#000000';
    const luminance = tryCatch(() => parseToHsl(fallbackColor).lightness, () => 1);
    if (luminance > 0.5) {
        return transparentize(0.5, '#ffffff');
    }
    return transparentize(0.95, '#ffffff');
};
/**
 * Converts a CSS time value to a number in milliseconds.
 *
 * @param time - The CSS time value as a string (e.g: "2s", "500ms") or a number. If undefined, returns 0.
 * @returns The time value in milliseconds.
 *   If the input is a number, it is returned as is.
 *   If the input is a string, it is parsed and converted to milliseconds.
 */
export const getCSSTimeInMilliseconds = (time) => {
    if (time === undefined)
        return 0;
    if (typeof time === 'number')
        return time;
    const [value, unit] = getValueAndUnit(time);
    if (unit === 's')
        return value * 1000;
    if (unit === 'ms')
        return value;
    return 0;
};
const getAlpha = (color) => ('alpha' in color ? color.alpha : 1);
/**
 * Compares two color strings to determine if they are equivalent.
 *
 * Parses both color strings into RGB values and compares their red, green, blue,
 * and alpha components. Returns false if either color string cannot be parsed.
 *
 * @param color1 - The first color string to compare
 * @param color2 - The second color string to compare
 * @returns True if both colors have identical RGBA values, false otherwise
 *
 * @example
 * isSameColor('#FF0000', 'rgb(255, 0, 0)') // true
 * isSameColor('#FF0000', '#00FF00') // false
 * isSameColor('invalid', '#FF0000') // false
 */
export const isSameColor = (color1, color2) => {
    try {
        const parsed1 = parseToRgb(color1);
        const parsed2 = parseToRgb(color2);
        return (parsed1.red === parsed2.red &&
            parsed1.green === parsed2.green &&
            parsed1.blue === parsed2.blue &&
            getAlpha(parsed1) === getAlpha(parsed2));
    }
    catch {
        return false;
    }
};
//# sourceMappingURL=utils.js.map