import findIndex from 'lodash/findIndex';
import {
    getClosestColorPaletteColor,
    getColorPalettesIndex,
    getRgbValuesFromString,
} from '../../../Services/DesignDataService';
import { hexToRgb, parseColorData } from '../../../Reducers/DesignArea/Selectors';
import { getAggregatedColors } from '../../../Reducers/DesignData/Selectors';

const removeColorFromIndexArray = (colorIndexArray, colorDataStr) => {
    const { palette, color: identifier } = parseColorData(colorDataStr);
    const idx = findIndex(colorIndexArray, { palette, identifier });
    idx !== -1 && colorIndexArray.splice(idx, 1);
};

/**
 * @param {object} colorsMap
 * @param {array} colorPalettes
 * @param {number} requiredColors
 */
export const expandVectorizeColorsMap = (colorsMap, colorPalettes, requiredColors) => {
    const availableColors = getColorPalettesIndex(colorPalettes);
    const expandedColorsMap = { ...colorsMap };

    const aggregatedColors = getAggregatedColors(colorsMap);
    const usedColors = Object.values(aggregatedColors);

    usedColors.forEach(({ identifier }) => removeColorFromIndexArray(availableColors, identifier));

    let colorsToFind = requiredColors - usedColors.length;

    if (colorsToFind < 1) {
        return expandedColorsMap;
    }

    for (const colorIdx of Object.keys(colorsMap)) {
        // skip if a color is already mapped to the key
        if (aggregatedColors[colorIdx]) {
            continue;
        }

        const replacementColor = getClosestColorPaletteColor(
            getRgbValuesFromString(hexToRgb(colorIdx)),
            availableColors
        );
        if (!replacementColor) {
            break;
        }
        expandedColorsMap[colorIdx] = { ...replacementColor };
        removeColorFromIndexArray(availableColors, replacementColor.identifier);
        if (!--colorsToFind || !availableColors.length) {
            break;
        }
    }
    return expandedColorsMap;
};

export const getClosestColorFromMap = (colorsMap, hexColor) => {
    const availableColors = Object.values(colorsMap)
        .filter(({ value }) => value !== hexColor)
        .map(color => {
            const { palette, color: identifier } = parseColorData(color.identifier);
            return {
                palette,
                identifier,
                valueObject: hexToRgb(color.value, false),
            };
        });
    return getClosestColorPaletteColor(hexToRgb(hexColor, false), availableColors);
};
