import DesignDataService, {
    getColorPalettesIndex,
    getClosestColorPaletteColor,
    getMissingColorPalettesColors,
    getRgbValuesFromString,
    getColorsDistance,
    applySvgContentOperations,
    getSvgColors,
    isColorTooBright,
    isWidget,
} from '../DesignDataService';
import ServiceLocator from '../../ServiceLocator';
import { toggleHighlight } from '../../Reducers/DesignArea/Actions';

describe('Services/DesignDataService', () => {
    let designDataService;
    let getCanvas;
    beforeEach(() => {
        designDataService = new DesignDataService();

        getCanvas = jest.fn();
        designDataService.registerGetCanvas(getCanvas);
    });

    describe('isColorTooBright', () => {
        test('returns false with a warning if any of the inputs are not supplied', () => {
            expect(isColorTooBright()).toBe(false);
            expect(isColorTooBright(22)).toBe(false);
            expect(isColorTooBright({ someRandomName: '42' })).toBe(false);
        });

        test('returns true if the input color is too bright', () => {
            const response = isColorTooBright({ r: 183, g: 255, b: 175 });

            expect(response).toBe(true);
        });

        test('returns false if the input color is not bright enough', () => {
            const response = isColorTooBright({ r: 183, g: 111, b: 175 });

            expect(response).toBe(false);
        });
    });

    describe('getScreenshots', () => {
        const fontMapping = {};

        beforeEach(() => {
            const getDesignAreas = jest
                .fn()
                .mockImplementation(() => [
                    { identifier: 'dummyIdentifier' },
                    { identifier: 'dummyIdentifier2' },
                    { identifier: 'dummyIdentifier3' },
                ]);
            designDataService.getDesignAreas = getDesignAreas.bind(designDataService);

            const _getCanvas = jest.fn().mockImplementation(({ identifier }) => ({
                getScreenshot: () => new Promise(resolve => resolve(`screenshot for area #${identifier}`)),
                getMaskHandler: () => ({
                    toggleOutline: () => () => null,
                }),
                getColorOverlay: () => null,
                objects: (id =>
                    ({
                        dummyIdentifier: [], // empty area to make sure it excludes,
                        dummyIdentifier2: [{ type: 'Text' }], // area with one element
                        dummyIdentifier3: [{ type: 'Text' }, { type: 'Image' }], // area with more elements
                    }[id]))(identifier),
            }));
            designDataService._getCanvas = _getCanvas.bind(designDataService);
        });
        test('returns a screenshot object, with only non-empty canvases on that object', async () => {
            const response = await designDataService.getScreenshots(fontMapping);

            expect(Object.keys(response)).toContain('dummyIdentifier2');
            expect(Object.keys(response)).toContain('dummyIdentifier3');
            expect(Object.keys(response)).not.toContain('dummyIdentifier');
        });

        test('waits for getScreenshot() function to resolve before returning', async () => {
            const response = await designDataService.getScreenshots(fontMapping);

            expect(response.dummyIdentifier2).not.toBeInstanceOf(Promise);
            expect(response.dummyIdentifier3).not.toBeInstanceOf(Promise);
        });
    });

    test('getDesignAreaByIdentifier returns the correct object', () => {
        const designArea = { identifier: 'three' };
        ServiceLocator.provide(
            new (class StoreService {
                static serviceName = 'StoreService';
                state = {
                    designArea: {
                        filteredDesignAreas: [{ identifier: 'one' }, { identifier: 'two' }, designArea],
                    },
                };
            })()
        );
        const srv = new DesignDataService();
        expect(srv.getDesignAreaByIdentifier('three')).toBe(designArea);
    });
    test('removeBulkNameItems calls canvasData Update', () => {
        const designdata = {
            rear_center: {
                canvasData: {
                    objects: [
                        {
                            isBulkName: true,
                            type: 'Text',
                        },
                    ],
                },
            },
        };
        ServiceLocator.provide(
            new (class StoreService {
                static serviceName = 'StoreService';
                state = {
                    designArea: {
                        selectedDesignArea: {
                            identifier: 'rear_center',
                        },
                    },
                    configurator: {
                        configuration: {
                            designdata,
                        },
                    },
                };
                dispatch = jest.fn();
            })()
        );
        const designdataForSelectedDesignArea = designdata.rear_center;
        const srv = new DesignDataService();
        srv.setCanvasData = jest.fn();
        srv.loadCanvasDataFromState = jest.fn();
        srv.removeBulkNameItems(designdataForSelectedDesignArea);
        expect(srv.setCanvasData).toHaveBeenCalledWith({ objects: [] });
        expect(srv.loadCanvasDataFromState).toHaveBeenCalledWith([{ identifier: 'rear_center' }]);
    });
    test('createHighlightMemo restores the highlight state correctly', () => {
        const mockStoreSrv = new (class StoreService {
            static serviceName = 'StoreService';
            state = {
                designArea: {
                    showHighlight: true,
                },
            };
            dispatch = jest.fn();
        })();
        ServiceLocator.provide(mockStoreSrv);
        const srv = new DesignDataService();
        srv.updateVisualization = jest.fn();
        const memo = srv.createHighlightMemo(false);
        expect(typeof memo).toEqual('object');
        expect(typeof memo.restore).toEqual('function');
        expect(mockStoreSrv.dispatch).toHaveBeenLastCalledWith(toggleHighlight(false));
        memo.restore();
        expect(mockStoreSrv.dispatch).toHaveBeenLastCalledWith(toggleHighlight(true));
    });

    test('getColorPalettesIndex returns the correct result', () => {
        const standardColorPalette = [
            {
                identifier: 'default',
                title: 'Standardfarben',
                colors: [
                    { identifier: 'black', hex_value: '000000', title: 'schwarz' },
                    { identifier: 'white', hex_value: 'ffffff', title: 'weiß' },
                    { identifier: 'yellow', hex_value: 'ffb800', title: 'gelb' },
                ],
            },
        ];

        expect(getColorPalettesIndex(standardColorPalette)).toEqual([
            {
                palette: 'default',
                identifier: 'black',
                value: 'rgb(0, 0, 0)',
                valueObject: { r: 0, g: 0, b: 0 },
            },
            {
                palette: 'default',
                identifier: 'white',
                value: 'rgb(255, 255, 255)',
                valueObject: { r: 255, g: 255, b: 255 },
            },
            {
                palette: 'default',
                identifier: 'yellow',
                value: 'rgb(255, 184, 0)',
                valueObject: { r: 255, g: 184, b: 0 },
            },
        ]);
    });

    test('getClosestColorPaletteColor returns the correct color', () => {
        const colorPalettesIndex = [
            {
                palette: 'default',
                identifier: 'black',
                value: 'rgb(0, 0, 0)',
                valueObject: { r: 0, g: 0, b: 0 },
            },
            {
                palette: 'default',
                identifier: 'white',
                value: 'rgb(255, 255, 255)',
                valueObject: { r: 255, g: 255, b: 255 },
            },
            {
                palette: 'default',
                identifier: 'yellow',
                value: 'rgb(255, 184, 0)',
                valueObject: { r: 255, g: 184, b: 0 },
            },
        ];

        const colors = {
            black: { identifier: '{"color":"black","palette":"default"}', value: '#000000' },
            white: { identifier: '{"color":"white","palette":"default"}', value: '#ffffff' },
            yellow: { identifier: '{"color":"yellow","palette":"default"}', value: '#ffb800' },
        };

        expect(getClosestColorPaletteColor({ r: 10, g: 0, b: 0 }, colorPalettesIndex)).toEqual(colors.black);
        expect(getClosestColorPaletteColor({ r: 255, g: 255, b: 200 }, colorPalettesIndex)).toEqual(
            colors.white
        );
        expect(getClosestColorPaletteColor({ r: 235, g: 150, b: 0 }, colorPalettesIndex)).toEqual(
            colors.yellow
        );
    });

    test('getMissingColorPalettesColors returns the correct colors', () => {
        const standardColorPalette = [
            {
                identifier: 'default',
                title: 'Standardfarben',
                colors: [
                    { identifier: 'black', hex_value: '000000', title: 'schwarz' },
                    { identifier: 'white', hex_value: 'ffffff', title: 'weiß' },
                    { identifier: 'yellow', hex_value: 'ffb800', title: 'gelb' },
                    { identifier: 'red', hex_value: 'f73429', title: 'rot' },
                    { identifier: 'blue', hex_value: '0078b8', title: 'blau' },
                    { identifier: 'pink', hex_value: 'ca0f86', title: 'rosa' },
                    { identifier: 'green', hex_value: '007755', title: 'grün' },
                    { identifier: 'brown', hex_value: '7e4531', title: 'braun' },
                    { identifier: 'gold', hex_value: '917b4c', title: 'gold' },
                    { identifier: 'silver', hex_value: '84888b', title: 'silber' },
                ],
            },
        ];

        const colorsInStandardColorPalette = [
            { identifier: '{"color":"red","palette":"default"}', value: 'rgb(247, 52, 41)' },
        ];

        const colorsNotInStandardColorPalette = [
            { identifier: '{"color":"fake_color","palette":"fake_palette"}', value: 'rgb(0, 0, 0)' },
        ];

        const customColors = [
            { identifier: '{"color":"00bbdd","palette":null,"custom":true}', value: 'rgb(0, 187, 221)' },
        ];

        expect(
            getMissingColorPalettesColors(colorsInStandardColorPalette, standardColorPalette, false)
        ).toEqual([]);

        expect(
            getMissingColorPalettesColors(colorsNotInStandardColorPalette, standardColorPalette, false)
        ).toEqual([
            {
                closestColor: { identifier: '{"color":"black","palette":"default"}', value: '#000000' },
                color: {
                    identifier: '{"color":"fake_color","palette":"fake_palette"}',
                    value: 'rgb(0, 0, 0)',
                },
            },
        ]);

        expect(getMissingColorPalettesColors(customColors, standardColorPalette, false)).toEqual([]);

        expect(getMissingColorPalettesColors(customColors, standardColorPalette, true)).toEqual([
            {
                closestColor: { identifier: '{"color":"blue","palette":"default"}', value: '#0078b8' },
                color: {
                    identifier: '{"color":"00bbdd","palette":null,"custom":true}',
                    value: 'rgb(0, 187, 221)',
                },
            },
        ]);
    });

    test('[INTEGRATION] selectDesignArea calls the ui.show action to show the designer', () => {
        const mockStoreSrv = new (class StoreService {
            static serviceName = 'StoreService';
            state = {
                designArea: {
                    selectedDesignArea: {},
                },
            };
            dispatch = jest.fn();
        })();
        ServiceLocator.provide(mockStoreSrv);
        const mockUISrv = new (class UIService {
            static serviceName = 'UIService';
            show = jest.fn();
        })();
        ServiceLocator.provide(mockUISrv);
        const mockVisualizationSrv = new (class VisualizationService {
            static serviceName = 'VisualizationService';
            disableUserMovement = jest.fn();
        })();
        ServiceLocator.provide(mockVisualizationSrv);

        const srv = new DesignDataService();
        srv.selectDesignArea('myDesignArea');
        expect(mockUISrv.show).toHaveBeenCalledWith('designer');
    });

    test('[INTEGRATION] removeDesignAreaPlaceholders removes empty text objects', () => {
        const mockStoreSrv = new (class StoreService {
            static serviceName = 'StoreService';
            state = {
                designArea: {
                    selectedDesignArea: {
                        identifier: 'fakeIdentifier',
                    },
                },
                configurator: {
                    configuration: {
                        designdata: {
                            fakeIdentifier: {
                                canvasData: {
                                    objects: [
                                        {
                                            type: 'Text',
                                            content: '<span>Fake text</span>',
                                        },
                                        {
                                            type: 'Text',
                                            content: '<span> </span>',
                                        },
                                        {
                                            type: 'Text',
                                            content: '<span data-placeholder="true">Fake text</span>',
                                        },
                                    ],
                                },
                            },
                        },
                    },
                },
            };
        })();
        ServiceLocator.provide(mockStoreSrv);

        const srv = new DesignDataService();

        srv.setCanvasData = jest.fn();
        srv.loadCanvasDataFromState = jest.fn();

        srv.removeDesignAreaPlaceholders();

        expect(srv.setCanvasData).toHaveBeenCalledWith({
            objects: [{ content: '<span>Fake text</span>', type: 'Text' }],
        });

        expect(srv.loadCanvasDataFromState).toHaveBeenCalledWith([{ identifier: 'fakeIdentifier' }]);
    });

    test('[INTEGRATION] removeDesignAreaPlaceholders removes placeholder image objects', () => {
        const mockStoreSrv = new (class StoreService {
            static serviceName = 'StoreService';
            state = {
                designArea: {
                    selectedDesignArea: {
                        identifier: 'fakeIdentifier',
                    },
                },
                configurator: {
                    configuration: {
                        designdata: {
                            fakeIdentifier: {
                                canvasData: {
                                    objects: [
                                        {
                                            type: 'Text',
                                            content: '<span>Fake text</span>',
                                        },
                                        {
                                            type: 'Image',
                                            imageData: {
                                                fileName: 'placeholder.jpg',
                                                isPlaceHolderImage: true,
                                            },
                                        },
                                        {
                                            type: 'Image',
                                            imageData: {
                                                fileName: 'testImage.jpg',
                                                isPlaceHolderImage: false,
                                            },
                                        },
                                    ],
                                },
                            },
                        },
                    },
                },
            };
        })();
        ServiceLocator.provide(mockStoreSrv);

        const srv = new DesignDataService();

        srv.setCanvasData = jest.fn();
        srv.loadCanvasDataFromState = jest.fn();

        srv.removeDesignAreaPlaceholders();

        expect(srv.setCanvasData).toHaveBeenCalledWith({
            objects: [
                {
                    type: 'Text',
                    content: '<span>Fake text</span>',
                },
                {
                    type: 'Image',
                    imageData: {
                        fileName: 'testImage.jpg',
                        isPlaceHolderImage: false,
                    },
                },
            ],
        });
    });

    test('[INTEGRATION] removeDesignAreaPlaceholders removes placeholder image and text objects', () => {
        const mockStoreSrv = new (class StoreService {
            static serviceName = 'StoreService';
            state = {
                designArea: {
                    selectedDesignArea: {
                        identifier: 'fakeIdentifier',
                    },
                },
                configurator: {
                    configuration: {
                        designdata: {
                            fakeIdentifier: {
                                canvasData: {
                                    objects: [
                                        {
                                            type: 'Text',
                                            content: '<span data-placeholder="true">Fake text</span>',
                                        },
                                        {
                                            type: 'Image',
                                            imageData: {
                                                fileName: 'placeholder.jpg',
                                                isPlaceHolderImage: true,
                                            },
                                        },
                                    ],
                                },
                            },
                        },
                    },
                },
            };
        })();
        ServiceLocator.provide(mockStoreSrv);

        const srv = new DesignDataService();

        srv.setCanvasData = jest.fn();
        srv.loadCanvasDataFromState = jest.fn();

        srv.removeDesignAreaPlaceholders();

        expect(srv.setCanvasData).toHaveBeenCalledWith({
            objects: [],
        });
    });

    test('[INTEGRATION] removeDesignAreaPlaceholders removes placeholder image and keeps placeholder text', () => {
        const placeholderText = {
            type: 'Text',
            content: '<span data-placeholder="true">Fake text</span>',
        };
        const mockStoreSrv = new (class StoreService {
            static serviceName = 'StoreService';
            state = {
                designArea: {
                    selectedDesignArea: {
                        identifier: 'fakeIdentifier',
                    },
                },
                configurator: {
                    configuration: {
                        designdata: {
                            fakeIdentifier: {
                                canvasData: {
                                    objects: [
                                        placeholderText,
                                        {
                                            type: 'Image',
                                            imageData: {
                                                fileName: 'placeholder.jpg',
                                                isPlaceHolderImage: true,
                                            },
                                        },
                                    ],
                                },
                            },
                        },
                    },
                },
            };
        })();
        ServiceLocator.provide(mockStoreSrv);

        const srv = new DesignDataService();

        srv.setCanvasData = jest.fn();
        srv.loadCanvasDataFromState = jest.fn();

        srv.removeDesignAreaPlaceholders(false, true);

        expect(srv.setCanvasData).toHaveBeenCalledWith({
            objects: [placeholderText],
        });
    });

    test('[INTEGRATION] removeDesignAreaPlaceholders removes placeholder text and keeps placeholder image', () => {
        const placeholderImage = {
            type: 'Image',
            imageData: {
                fileName: 'placeholder.jpg',
                isPlaceHolderImage: true,
            },
        };
        const mockStoreSrv = new (class StoreService {
            static serviceName = 'StoreService';
            state = {
                designArea: {
                    selectedDesignArea: {
                        identifier: 'fakeIdentifier',
                    },
                },
                configurator: {
                    configuration: {
                        designdata: {
                            fakeIdentifier: {
                                canvasData: {
                                    objects: [
                                        {
                                            type: 'Text',
                                            content: '<span data-placeholder="true">Fake text</span>',
                                        },
                                        placeholderImage,
                                    ],
                                },
                            },
                        },
                    },
                },
            };
        })();
        ServiceLocator.provide(mockStoreSrv);

        const srv = new DesignDataService();

        srv.setCanvasData = jest.fn();
        srv.loadCanvasDataFromState = jest.fn();

        srv.removeDesignAreaPlaceholders(true, false);

        expect(srv.setCanvasData).toHaveBeenCalledWith({
            objects: [placeholderImage],
        });
    });

    test(
        '[INTEGRATION] openDesignAreaEditor calls the ui.show action to show the designer, and calls the ' +
            'selectFirstDesignArea because no designArea is selected',
        () => {
            const mockStoreSrv = new (class StoreService {
                static serviceName = 'StoreService';
                state = {
                    configurator: {
                        configuration: {
                            designData: {},
                        },
                    },
                    designArea: {
                        selectedDesignArea: {},
                        previousEditedDesignArea: {},
                    },
                    designView: {
                        selectedDesignView: {},
                    },
                };
                dispatch = jest.fn();
            })();
            ServiceLocator.provide(mockStoreSrv);
            const mockUISrv = new (class UIService {
                static serviceName = 'UIService';
                show = jest.fn();
            })();
            ServiceLocator.provide(mockUISrv);
            const mockVisualizationSrv = new (class VisualizationService {
                static serviceName = 'VisualizationService';
                enableUserMovement = jest.fn();
                freeUserMovement = jest.fn();
                getActiveDesignArea = jest.fn();
            })();
            ServiceLocator.provide(mockVisualizationSrv);

            const srv = new DesignDataService();
            srv.selectFirstDesignArea = jest.fn();
            srv.openDesignAreaEditor();
            expect(mockUISrv.show).toHaveBeenCalledWith('designer');
            expect(srv.selectFirstDesignArea).toHaveBeenCalled();
        }
    );
    test(
        '[INTEGRATION] openDesignAreaEditor calls the ui.show action to show the designer, and calls the ' +
            'designArea from designView because a designView is selected',
        () => {
            const mockStoreSrv = new (class StoreService {
                static serviceName = 'StoreService';
                state = {
                    configurator: {
                        configuration: {
                            designData: {},
                        },
                    },
                    designArea: {
                        selectedDesignArea: {},
                        previousEditedDesignArea: {},
                        filteredDesignAreas: [
                            {
                                identifier: 'back',
                                designView: {
                                    identifier: '03_back',
                                },
                                designProductionMethods: [],
                            },
                            {
                                identifier: 'front',
                                designView: {
                                    identifier: '02_front',
                                },
                                designProductionMethods: [],
                            },
                            {
                                identifier: 'side',
                                designView: {
                                    identifier: '01_side',
                                },
                                designProductionMethods: [],
                            },
                        ],
                    },
                    designView: {
                        selectedDesignView: {
                            identifier: '01_side',
                        },
                    },
                };
                dispatch = jest.fn();
            })();
            ServiceLocator.provide(mockStoreSrv);
            const mockUISrv = new (class UIService {
                static serviceName = 'UIService';
                show = jest.fn();
            })();
            ServiceLocator.provide(mockUISrv);
            const mockVisualizationSrv = new (class VisualizationService {
                static serviceName = 'VisualizationService';
                enableUserMovement = jest.fn();
                disableUserMovement = jest.fn();
                freeUserMovement = jest.fn();
                getActiveDesignArea = jest.fn();
            })();
            ServiceLocator.provide(mockVisualizationSrv);

            const srv = new DesignDataService();
            srv.selectDesignArea = jest.fn();
            srv.openDesignAreaEditor();
            expect(mockUISrv.show).toHaveBeenCalledWith('designer');
            expect(srv.selectDesignArea).toHaveBeenCalledWith('side');
        }
    );
    test(
        '[INTEGRATION] openDesignAreaEditor calls the ui.show action to show the designer, and calls the ' +
            'designArea from designData with objects to open',
        () => {
            const mockStoreSrv = new (class StoreService {
                static serviceName = 'StoreService';
                state = {
                    configurator: {
                        configuration: {
                            designdata: {
                                a_1: {
                                    canvasData: {
                                        objects: [],
                                    },
                                },
                                c_1: {
                                    canvasData: {
                                        objects: [{ type: 'Text' }],
                                    },
                                },
                                a_2: {
                                    canvasData: null,
                                },
                                c_2: {
                                    canvasData: {
                                        objects: [{ type: 'Text' }],
                                    },
                                },
                            },
                        },
                    },
                    designArea: {
                        selectedDesignArea: {},
                        previousEditedDesignArea: {},
                    },
                    designView: {
                        selectedDesignView: {},
                    },
                };
                dispatch = jest.fn();
            })();
            ServiceLocator.provide(mockStoreSrv);
            const mockUISrv = new (class UIService {
                static serviceName = 'UIService';
                show = jest.fn();
            })();
            ServiceLocator.provide(mockUISrv);
            const mockVisualizationSrv = new (class VisualizationService {
                static serviceName = 'VisualizationService';
                enableUserMovement = jest.fn();
                freeUserMovement = jest.fn();
                getActiveDesignArea = jest.fn();
            })();
            ServiceLocator.provide(mockVisualizationSrv);

            const srv = new DesignDataService();
            srv.selectDesignArea = jest.fn();
            srv.openDesignAreaEditor();
            expect(mockUISrv.show).toHaveBeenCalledWith('designer');
            expect(srv.selectDesignArea).toHaveBeenCalledWith('c_1');
        }
    );
    test(
        '[INTEGRATION] openDesignAreaEditor calls the ui.show action to show the designer, and calls the ' +
            'selectDesignArea because no designArea is selected but has previous edited Design Area',
        () => {
            const mockStoreSrv = new (class StoreService {
                static serviceName = 'StoreService';
                state = {
                    configurator: {
                        configuration: {
                            designData: {},
                        },
                    },
                    designArea: {
                        selectedDesignArea: {},
                        previousEditedDesignArea: {
                            identifier: 'area-51',
                        },
                    },
                    designView: {
                        selectedDesignView: {},
                    },
                };
                dispatch = jest.fn();
            })();
            ServiceLocator.provide(mockStoreSrv);
            const mockUISrv = new (class UIService {
                static serviceName = 'UIService';
                show = jest.fn();
            })();
            ServiceLocator.provide(mockUISrv);
            const mockVisualizationSrv = new (class VisualizationService {
                static serviceName = 'VisualizationService';
                enableUserMovement = jest.fn();
                freeUserMovement = jest.fn();
                getActiveDesignArea = jest.fn();
            })();
            ServiceLocator.provide(mockVisualizationSrv);

            const srv = new DesignDataService();
            srv.selectDesignArea = jest.fn();
            srv.openDesignAreaEditor();
            expect(mockUISrv.show).toHaveBeenCalledWith('designer');
            expect(srv.selectDesignArea).toHaveBeenCalled();
        }
    );

    test(
        '[INTEGRATION] openDesignAreaEditor calls the ui.show action to show the designer, but does not call ' +
            'selectFirstDesignArea since a design area is already selected',
        () => {
            const mockStoreSrv = new (class StoreService {
                static serviceName = 'StoreService';
                state = {
                    designArea: {
                        selectedDesignArea: {
                            identifier: 'area-51',
                        },
                        previousEditedDesignArea: {},
                    },
                    designView: {
                        selectedDesignView: {},
                    },
                    configurator: {
                        configuration: {
                            designdata: {
                                'area-51': {
                                    canvasData: {
                                        objects: [],
                                    },
                                },
                            },
                        },
                    },
                };
                dispatch = jest.fn();
            })();
            ServiceLocator.provide(mockStoreSrv);
            const mockUISrv = new (class UIService {
                static serviceName = 'UIService';
                show = jest.fn();
            })();
            ServiceLocator.provide(mockUISrv);
            const mockVisualizationSrv = new (class VisualizationService {
                static serviceName = 'VisualizationService';
                enableUserMovement = jest.fn();
                disableUserMovement = jest.fn();
                freeUserMovement = jest.fn();
                getActiveDesignArea = jest.fn();
            })();
            ServiceLocator.provide(mockVisualizationSrv);

            const srv = new DesignDataService();
            srv.selectFirstDesignArea = jest.fn();
            srv._getCanvas = jest.fn();
            srv.openDesignAreaEditor();
            expect(mockUISrv.show).toHaveBeenCalledWith('designer');
            expect(srv.selectFirstDesignArea).not.toHaveBeenCalled();
        }
    );

    test('getRgbValuesFromString returns the correct rgb values', () => {
        expect(getRgbValuesFromString('rgb(123, 36, 0)')).toEqual({ r: 123, g: 36, b: 0 });
    });

    test('getRgbValuesFromString returns the default value if the input does not match the rgb(0,0,0) format', () => {
        const defaultValue = { r: 64, g: 64, b: 64 };
        expect(getRgbValuesFromString('', defaultValue)).toBe(defaultValue);
        expect(getRgbValuesFromString('#666', defaultValue)).toBe(defaultValue);
        expect(getRgbValuesFromString('blue', defaultValue)).toBe(defaultValue);
    });

    test('getColorsDistance returns the correct color distance', () => {
        expect(getColorsDistance({ r: 123, g: 36, b: 0 }, { r: 123, g: 36, b: 0 })).toEqual(0);
        expect(getColorsDistance({ r: 123, g: 36, b: 0 }, { r: 123, g: 36, b: 10 })).toEqual(100);
        expect(getColorsDistance({ r: 123, g: 36, b: 0 }, { r: 23, g: 36, b: 30 })).toEqual(10900);
    });

    test('applySvgContentOperations returns the correct src', () => {
        const original = {
            format: 'SVG',
        };
        const preview = {
            width: 200,
            height: 100,
        };
        const operations = {
            vectorize: true,
            vectorizeColorsMap: {
                '#ff0000': { value: '#0000ff' },
            },
        };

        const getResult = (original, preview, operations, svgContent) =>
            atob(
                applySvgContentOperations(original, preview, operations, svgContent).replace(
                    /^data:image\/svg\+xml;base64,/,
                    ''
                )
            );

        const svgContentWithoutWidthHeight = '<svg><circle r="10" fill="#ff0000" /></svg>';
        const svgContentWithWidthHeight =
            '<svg width="2048px" height="1024px" viewBox="0 0 2048 1024"><circle r="10" fill="#0000ff" /></svg>';

        expect(getResult(original, preview, operations, svgContentWithoutWidthHeight)).toEqual(
            svgContentWithWidthHeight
        );
        expect(getResult(original, preview, operations, svgContentWithWidthHeight)).toEqual(
            svgContentWithWidthHeight
        );
    });

    describe('getSvgColors', () => {
        test('returns the correct matching colors', () => {
            const designProductionMethodWithExactColors = {
                colorPalettes: [
                    {
                        identifier: 'default',
                        title: 'Standardfarben',
                        colors: [
                            {
                                identifier: 'white',
                                hex_value: 'ffffff',
                                title: 'weiss',
                            },
                            {
                                identifier: 'black',
                                hex_value: '000000',
                                title: 'schwarz',
                            },
                        ],
                    },
                ],
            };
            expect(
                getSvgColors(
                    '<svg><circle r="10" fill="#ffffff" /><circle r="3" fill="#000000" /></svg>',
                    designProductionMethodWithExactColors
                )
            ).toEqual([
                {
                    color: {
                        identifier: '{"color":"white","palette":"default"}',
                        value: '#ffffff',
                    },
                    key: '#ffffff',
                },
                {
                    color: {
                        identifier: '{"color":"black","palette":"default"}',
                        value: '#000000',
                    },
                    key: '#000000',
                },
            ]);
        });
        test('returns the closest colors from the color palette', () => {
            const designProductionMethodWithColors = {
                colorPalettes: [
                    {
                        identifier: 'default',
                        title: 'Standardfarben',
                        colors: [
                            {
                                identifier: 'white',
                                hex_value: 'ffffff',
                                title: 'weiss',
                            },
                            {
                                identifier: 'black',
                                hex_value: '000000',
                                title: 'schwarz',
                            },
                        ],
                    },
                ],
            };
            expect(
                getSvgColors(
                    '<svg><circle r="10" fill="#606060" /><circle r="10" fill="#A0A0A0" /></svg>',
                    designProductionMethodWithColors
                )
            ).toEqual([
                {
                    color: { identifier: '{"color":"black","palette":"default"}', value: '#000000' },
                    key: '#606060',
                },
                {
                    color: { identifier: '{"color":"white","palette":"default"}', value: '#ffffff' },
                    key: '#a0a0a0',
                },
            ]);
        });
        test('empty palettes / fallback mode -> returns the colors as custom colors', () => {
            const designProductionMethodWithoutColors = {
                colorPalettes: [],
            };
            expect(
                getSvgColors(
                    '<svg><circle r="10" fill="#606060" /><circle r="10" fill="#A0A0A0" /></svg>',
                    designProductionMethodWithoutColors
                )
            ).toEqual([
                {
                    color: {
                        identifier: '{"color":"#606060","palette":null,"custom":true}',
                        value: '#606060',
                    },
                    key: '#606060',
                },
                {
                    color: {
                        identifier: '{"color":"#a0a0a0","palette":null,"custom":true}',
                        value: '#a0a0a0',
                    },
                    key: '#a0a0a0',
                },
            ]);
        });
    });

    test('isWidget returns the correct result', () => {
        expect(isWidget('/widget/identifier:fake_id')).toEqual(true);
        expect(isWidget('/identifier:fake_id')).toEqual(false);
    });

    describe('resetEditedFile resets the operations correctly', () => {
        const originalColorsMap = {
            '#000000': {
                identifier: '{"color":"black","palette":"default"}',
                value: '#000000',
            },
        };
        const modifiedColorsMap = {
            '#000000': {
                identifier: '{"color":"red","palette":"default"}',
                value: 'rgb(255, 0, 0)',
            },
        };
        const image = {
            operations: {
                vectorizeColorsMap: modifiedColorsMap,
                vectorizeOriginalColorsMap: originalColorsMap,
            },
        };

        test('case: gallery images', async () => {
            const galleryImage = {
                ...image,
                gallery: true,
            };
            const mockStoreSrv = new (class StoreService {
                static serviceName = 'StoreService';
                state = {
                    imageGallery: {
                        selectedImage: galleryImage,
                    },
                };
                dispatch = jest.fn();
            })();
            ServiceLocator.provide(mockStoreSrv);

            const srv = new DesignDataService();
            srv.editFileQueued = jest.fn();
            await srv.resetEditedFile();
            expect(srv.editFileQueued).toBeCalledWith(
                { vectorizeColorsMap: originalColorsMap, vectorizeOriginalColorsMap: originalColorsMap },
                galleryImage
            );
        });
        test('case: user images if vectors required by the production method', async () => {
            const mockStoreSrv = new (class StoreService {
                static serviceName = 'StoreService';
                state = {
                    configurator: {
                        configuration: {
                            designdata: {
                                area_1: {
                                    designProductionMethodIdentifier: 'embroidery',
                                },
                            },
                        },
                    },
                    designArea: {
                        selectedDesignArea: {
                            identifier: 'area_1',
                            designProductionMethods: [
                                {
                                    identifier: 'embroidery',
                                    options: {
                                        maxColorAmount: 4,
                                        vectorsRequired: true,
                                    },
                                    colorPalettes: [
                                        {
                                            identifier: 'default',
                                        },
                                    ],
                                },
                            ],
                        },
                    },
                    imageGallery: {
                        selectedImage: image,
                    },
                };
                dispatch = jest.fn();
            })();
            ServiceLocator.provide(mockStoreSrv);

            const srv = new DesignDataService();
            srv.editFileQueued = jest.fn();
            await srv.resetEditedFile();
            expect(srv.editFileQueued).toBeCalledWith(
                {
                    vectorizeColorsMap: originalColorsMap,
                    vectorizeOriginalColorsMap: originalColorsMap,
                    vectorizeThreshold: null,
                },
                image
            );
        });
        test('case: user images if vectors NOT required by the production method', async () => {
            const mockStoreSrv = new (class StoreService {
                static serviceName = 'StoreService';
                state = {
                    configurator: {
                        configuration: {
                            designdata: {
                                area_1: {
                                    designProductionMethodIdentifier: 'digital_printing',
                                },
                            },
                        },
                    },
                    designArea: {
                        selectedDesignArea: {
                            identifier: 'area_1',
                            designProductionMethods: [
                                {
                                    identifier: 'digital_printing',
                                    options: {
                                        vectorsRequired: false,
                                    },
                                    colorPalettes: [
                                        {
                                            identifier: 'default',
                                        },
                                    ],
                                },
                            ],
                        },
                    },
                    imageGallery: {
                        selectedImage: image,
                    },
                };
                dispatch = jest.fn();
            })();
            ServiceLocator.provide(mockStoreSrv);

            const srv = new DesignDataService();
            srv.editFileQueued = jest.fn();
            await srv.resetEditedFile();
            expect(srv.editFileQueued).toBeCalledWith(
                {
                    vectorize: false,
                    vectorizeThreshold: null,
                    vectorizeMaxColorAmount: undefined,
                    vectorizeColorsMap: {},
                    vectorizeOriginalColorsMap: {},
                    vectorizeMonochrome: false,
                },
                image
            );
        });
    });
});
