import {
    reduceNumberOfDistinctColorsBy,
    createVectorizeColorsMap,
    applyProductionMethodChangeToCanvasObjects,
} from '../Modifiers';

describe('Reducers/DesignData/Modifiers', () => {
    describe('createVectorizeColorsMap returns the correct result', () => {
        test('for empty oldColorsMap', () => {
            const svgColors = [
                {
                    color: {
                        identifier: '{"color":"white","palette":"default"}',
                        value: '#ffffff',
                    },
                    key: '#ffffff',
                },
                {
                    color: {
                        identifier: '{"color":"black","palette":"default"}',
                        value: '#000000',
                    },
                    key: '#000000',
                },
            ];
            const colorsMap = createVectorizeColorsMap(undefined, svgColors);
            expect(colorsMap).toEqual({
                '#ffffff': {
                    identifier: '{"color":"white","palette":"default"}',
                    value: '#ffffff',
                },
                '#000000': {
                    identifier: '{"color":"black","palette":"default"}',
                    value: '#000000',
                },
            });
        });

        test('the color map has priority over svg colors', () => {
            const currentColorsMap = {
                '#ffffff': {
                    identifier: '{"color":"red","palette":"default"}',
                    value: '#ff0000',
                },
                '#000000': {
                    identifier: '{"color":"dark-grey","palette":"default"}',
                    value: '#202020',
                },
                '#ff00ff': {
                    identifier: '{"color":"white","palette":"default"}',
                    value: '#ffffff',
                },
            };
            const svgColors = [
                {
                    color: {
                        identifier: '{"color":"white","palette":"default"}',
                        value: '#ffffff',
                    },
                    key: '#ffffff',
                },
                {
                    color: {
                        identifier: '{"color":"black","palette":"default"}',
                        value: '#000000',
                    },
                    key: '#000000',
                },
                {
                    color: {
                        identifier: '{"color":"magenta","palette":"default"}',
                        value: '#ff00ff',
                    },
                    key: '#ff00ff',
                },
            ];
            const colorsMap = createVectorizeColorsMap(currentColorsMap, svgColors);
            expect(colorsMap).toEqual({
                '#ffffff': {
                    identifier: '{"color":"red","palette":"default"}',
                    value: '#ff0000',
                },
                '#000000': {
                    identifier: '{"color":"dark-grey","palette":"default"}',
                    value: '#202020',
                },
                '#ff00ff': {
                    identifier: '{"color":"white","palette":"default"}',
                    value: '#ffffff',
                },
            });
        });

        test('increasing colors: the non-mapped keys area added from the svg colors', () => {
            const currentColorsMap = {
                '#ffffff': {
                    identifier: '{"color":"red","palette":"default"}',
                    value: '#ff0000',
                },
            };
            const svgColors = [
                {
                    color: {
                        identifier: '{"color":"white","palette":"default"}',
                        value: '#ffffff',
                    },
                    key: '#ffffff',
                },
                {
                    color: {
                        identifier: '{"color":"black","palette":"default"}',
                        value: '#000000',
                    },
                    key: '#000000',
                },
                {
                    color: {
                        identifier: '{"color":"magenta","palette":"default"}',
                        value: '#ff00ff',
                    },
                    key: '#ff00ff',
                },
            ];
            const colorsMap = createVectorizeColorsMap(currentColorsMap, svgColors);
            expect(colorsMap).toEqual({
                '#ffffff': {
                    identifier: '{"color":"red","palette":"default"}',
                    value: '#ff0000',
                },
                '#000000': {
                    identifier: '{"color":"black","palette":"default"}',
                    value: '#000000',
                },
                '#ff00ff': {
                    identifier: '{"color":"magenta","palette":"default"}',
                    value: '#ff00ff',
                },
            });
        });
    });
    describe('reduceNumberOfDistinctColorsBy', () => {
        test('reduces the number of colors by 1', () => {
            const vectorizeColorsMap = {
                '#ffffff': {
                    identifier: '{"color":"red","palette":"default"}',
                    value: '#ff0000',
                },
                '#000000': {
                    identifier: '{"color":"green","palette":"default"}',
                    value: '#00ff00',
                },
            };

            expect(reduceNumberOfDistinctColorsBy(vectorizeColorsMap, 1)).toEqual({
                '#ffffff': {
                    identifier: '{"color":"green","palette":"default"}',
                    value: '#00ff00',
                },
                '#000000': {
                    identifier: '{"color":"green","palette":"default"}',
                    value: '#00ff00',
                },
            });
        });

        test('reduces the number of colors by 2', () => {
            const vectorizeColorsMap = {
                '#ffffff': {
                    identifier: '{"color":"red","palette":"default"}',
                    value: '#ff0000',
                },
                '#000000': {
                    identifier: '{"color":"green","palette":"default"}',
                    value: '#00ff00',
                },
                '#000011': {
                    identifier: '{"color":"blue","palette":"default"}',
                    value: '#0000ff',
                },
            };

            expect(reduceNumberOfDistinctColorsBy(vectorizeColorsMap, 2)).toEqual({
                '#ffffff': {
                    identifier: '{"color":"blue","palette":"default"}',
                    value: '#0000ff',
                },
                '#000000': {
                    identifier: '{"color":"blue","palette":"default"}',
                    value: '#0000ff',
                },
                '#000011': {
                    identifier: '{"color":"blue","palette":"default"}',
                    value: '#0000ff',
                },
            });
        });

        test('overwrites all key values if they originally had the same identifier', () => {
            const vectorizeColorsMap = {
                '#ffffff': {
                    identifier: '{"color":"red","palette":"default"}',
                    value: '#ff0000',
                },
                '#000000': {
                    identifier: '{"color":"red","palette":"default"}',
                    value: '#ff0000',
                },
                '#202020': {
                    identifier: '{"color":"yellow","palette":"default"}',
                    value: '#ffff00',
                },
            };

            expect(reduceNumberOfDistinctColorsBy(vectorizeColorsMap, 1)).toEqual({
                '#ffffff': {
                    identifier: '{"color":"yellow","palette":"default"}',
                    value: '#ffff00',
                },
                '#000000': {
                    identifier: '{"color":"yellow","palette":"default"}',
                    value: '#ffff00',
                },
                '#202020': {
                    identifier: '{"color":"yellow","palette":"default"}',
                    value: '#ffff00',
                },
            });
        });

        test('throws an error if it was called with malformed vectorizeColorsMap', () => {
            const vectorizeColorsMap = {
                '#ffffff': {
                    identifier: '{"color":"red","palette":"default"}',
                    value: '#ff0000',
                },
            };

            expect(() => {
                reduceNumberOfDistinctColorsBy(vectorizeColorsMap, 1);
            }).toThrow(
                'vectorizeColorsMap must have more unique colors than the number of colors we are reducing it by'
            );

            const largerVectorizeColorsMap = {
                '#ffffff': {
                    identifier: '{"color":"red","palette":"default"}',
                    value: '#ff0000',
                },
                '#000000': {
                    identifier: '{"color":"yellow","palette":"default"}',
                    value: '#ffff00',
                },
            };

            expect(() => {
                reduceNumberOfDistinctColorsBy(largerVectorizeColorsMap, 2);
            }).toThrow(
                'vectorizeColorsMap must have more unique colors than the number of colors we are reducing it by'
            );
        });
    });
    describe('applyProductionMethodChangeToCanvasObjects', () => {
        it('sets the "locked" and "autoFit" design element properties to the value of "designElementsLocked" and sets the rotation to 0', () => {
            const prevProductionMethod = { designElementsLocked: false };
            const nextProductionMethod = { designElementsLocked: true };
            const objects = [
                { type: 'Text', rotation: 90, autoFit: false, locked: false },
                { type: 'Image', rotation: -5, autoFit: false, locked: false },
            ];
            const newObjects = applyProductionMethodChangeToCanvasObjects(
                nextProductionMethod,
                prevProductionMethod,
                objects
            );
            expect(newObjects).toEqual([
                { type: 'Text', rotation: 0, autoFit: true, locked: true },
                { type: 'Image', rotation: 0, autoFit: true, locked: true },
            ]);
            expect(newObjects).not.toBe(objects);
        });
        it('adjusts the position of elements and font size to the new design area size', () => {
            const prevProductionMethod = { width: 100, height: 50 };
            const nextProductionMethod = { width: 80, height: 40 };
            const objects = [
                { type: 'Text', fontSize: 40, x: 50, y: 25 },
                { type: 'Image', x: 60, y: 30 },
            ];
            const newObjects = applyProductionMethodChangeToCanvasObjects(
                nextProductionMethod,
                prevProductionMethod,
                objects
            );
            expect(newObjects).toEqual([
                { type: 'Text', fontSize: 32, x: 40, y: 20 },
                { type: 'Image', x: 48, y: 24 },
            ]);
            expect(newObjects).not.toBe(objects);
        });
        it('keeps the original objects array (with reference) if there was no update', () => {
            const prevProductionMethod = { width: 100, height: 50, designElementsLocked: false };
            const nextProductionMethod = { width: 100, height: 50, designElementsLocked: false };
            const objects = [
                { type: 'Text', fontSize: 40, x: 50, y: 25 },
                { type: 'Image', x: 60, y: 30 },
            ];
            const newObjects = applyProductionMethodChangeToCanvasObjects(
                nextProductionMethod,
                prevProductionMethod,
                objects
            );
            expect(newObjects).toEqual(objects);
            expect(newObjects).toBe(objects);
        });
    });
});
