import { createAsyncTask } from '../../UI/Actions';
import { createDefaultReceiver, fetchDataAsync, postDataAsync } from '../../Actions';
import {
    dismissError,
    editImage,
    fetchGallery,
    fetchTags,
    getGalleryUrlForTags,
    receiveGalleryTags,
    selectTags,
    uploadImage,
    addImagesFromDesignArea,
    addGalleryImageToUserImages,
    setSelectedImageByIdentifier,
    SELECT_GALLERY_TAGS,
    URL_GALLERY,
    URL_TAGS,
    URL_UPLOAD,
    RECEIVE_GALLERY,
    RECEIVE_IMAGE_UPLOAD_DATA,
    WN_LOAD_IMAGES,
    WN_LOAD_TAGS,
    DISMISS_ERROR,
    ADD_IMAGES_FROM_DESIGN_AREA,
    ADD_GALLERY_IMAGE_TO_USER_IMAGES,
    SET_SELECTED_IMAGE,
} from '../Actions';
import { formDataToJSON } from '../../../../Utils/Test/formDataToJSON';
import { calculateImageBrightness } from '../../../Services/DesignDataService';

jest.mock('../../Actions');
jest.mock('../../UI/Actions');
jest.mock('../../../Services/DesignDataService');

/*skipped Tests should be updated , the tests run properly in test file but fail globally in 'npm run test'*/
describe('Reducers/ImageGallery/Actions', () => {
    afterEach(() => {
        jest.clearAllMocks();
    });

    it('getGalleryUrlForTags encodes tags as comma separated query params', () => {
        const tags = [
            { title: 'tag1', checked: true },
            { title: 'tag2', checked: true },
        ];
        expect(getGalleryUrlForTags(tags)).toBe(URL_GALLERY.replace('{tag}', 'tag1%2Ctag2'));
    });

    it('fetchTags calls fetchDataAsync with the correct url and receive action creator', () => {
        const ref = jest.fn();
        fetchDataAsync.mockImplementationOnce(() => ref);
        fetchTags();
        expect(createAsyncTask).toBeCalledWith(WN_LOAD_TAGS, ref);
        expect(fetchDataAsync.mock.calls[0][0]).toBe(URL_TAGS);
        expect(fetchDataAsync.mock.calls[0][1]).toBe(receiveGalleryTags);
    });
    it('selectTags calls dispatch with the correct action and calls dispatch with the fetchGalleryAction too', () => {
        const tags = [{ title: 'Cars', checked: true }];
        const dispatch = jest.fn();
        selectTags(tags)(dispatch);
        expect(dispatch.mock.calls[0][0]).toEqual({
            type: SELECT_GALLERY_TAGS,
            tags,
        });
        expect(fetchDataAsync.mock.calls[0][0]).toBe(getGalleryUrlForTags(tags));
    });
    it('fetchGallery calls fetchDataAsync with the correct url and receive action creator', () => {
        const mockResult = jest.fn(() => ({}));
        const fetchDataAsyncSpy = jest.fn(() => mockResult);
        fetchDataAsync.mockImplementationOnce(fetchDataAsyncSpy);
        const tags = [{ title: 'Cars' }, { title: 'Pandas' }];
        fetchGallery(tags);
        expect(createAsyncTask).toBeCalledWith(WN_LOAD_IMAGES, mockResult);
        expect(fetchDataAsync.mock.calls[0][0]).toBe(getGalleryUrlForTags(tags));
        // make sure that it creates the correct action
        expect(createDefaultReceiver).toBeCalledWith(RECEIVE_GALLERY);
    });
    it('uploadImage calls postDataAsync with the correct params', async () => {
        const fileName = 'test.png';
        createAsyncTask.mockImplementationOnce((name, action) => action);
        calculateImageBrightness.mockImplementationOnce(image => image);
        postDataAsync.mockResolvedValueOnce({
            fileName,
        });
        const dispatch = jest.fn();
        const getState = () => ({
            configurator: {
                configuration: {
                    designdata: {
                        designArea1: {
                            designProductionMethodIdentifier: 'customPrinting',
                        },
                    },
                },
            },
            designArea: {
                selectedDesignArea: {
                    identifier: 'designArea1',
                    mask: null,
                    designProductionMethods: [
                        {
                            identifier: 'customPrinting',
                            mask: null,
                            options: {
                                maxColorAmount: 4,
                                vectorsRequired: true,
                                vectorizedLogoMandatory: true,
                            },
                            colorPalettes: [
                                {
                                    identifier: 'default',
                                },
                            ],
                        },
                    ],
                },
            },
        });
        await uploadImage(fileName)(dispatch, getState);
        expect(postDataAsync.mock.calls[0][0]).toEqual(URL_UPLOAD);
        expect(formDataToJSON(postDataAsync.mock.calls[0][1]).userImage).toEqual(fileName);
        expect(createDefaultReceiver.mock.calls[0][0]).toBe(RECEIVE_IMAGE_UPLOAD_DATA);
        expect(createDefaultReceiver.mock.calls[0][1]).toMatchObject({ vectorizedLogoMandatory: true });
    });
    it('editImage calls postDataAsync with the correct params', async () => {
        const fileName = 'test.png';
        createAsyncTask.mockImplementationOnce((name, action) => action);
        postDataAsync.mockResolvedValueOnce({
            fileName,
        });
        const dispatch = jest.fn();
        const editData = {
            fileName,
            operations: [
                {
                    identifier: 'clipping',
                    config: { command: 'flood', backgroundColor: '#DF151E' },
                },
            ],
        };
        const getState = () => ({
            configurator: {
                configuration: {
                    designdata: {
                        designArea1: {
                            designProductionMethodIdentifier: 'customPrinting',
                        },
                    },
                },
            },
            designArea: {
                selectedDesignArea: {
                    identifier: 'designArea1',
                    mask: null,
                    designProductionMethods: [
                        {
                            identifier: 'customPrinting',
                            mask: null,
                            options: {
                                maxColorAmount: 4,
                                vectorsRequired: true,
                                vectorizedLogoMandatory: true,
                            },
                            colorPalettes: [
                                {
                                    identifier: 'default',
                                },
                            ],
                        },
                    ],
                },
            },
        });
        await editImage(editData)(dispatch, getState);
        expect(postDataAsync.mock.calls[0][0]).toEqual(URL_UPLOAD);
        expect(formDataToJSON(postDataAsync.mock.calls[0][1]).userImageEditData).toEqual(
            JSON.stringify(editData)
        );
        expect(createDefaultReceiver.mock.calls[0][0]).toBe(RECEIVE_IMAGE_UPLOAD_DATA);
        expect(createDefaultReceiver.mock.calls[0][1]).toMatchObject({ vectorizedLogoMandatory: true });
    });
    it('dismissError creates the correct action', () => {
        const dispatch = jest.fn();
        const getEmptyState = () => ({
            imageGallery: {
                lastErrorCode: null,
            },
        });
        const getStateWithError = () => ({
            imageGallery: {
                lastErrorCode: 'wrong_file',
            },
        });
        dismissError()(dispatch, getEmptyState);
        expect(dispatch).not.toBeCalled();
        dismissError()(dispatch, getStateWithError);
        expect(dispatch).toBeCalledWith({
            type: DISMISS_ERROR,
        });
    });

    it('addImagesFromDesignArea creates the action with the correct parameters', () => {
        const state = {
            configuration: {
                designdata: {
                    a_1: {
                        canvasData: {
                            objects: [
                                {
                                    type: 'Image',
                                    imageData: {
                                        fileName: '9c1330f774e4dada3c1bc8e2535143c3',
                                        preview: {
                                            url:
                                                '/img/uploads/designer/preview/9c1330f774e4dada3c1bc8e2535143c3.svg',
                                        },
                                    },
                                },
                            ],
                        },
                    },
                },
            },
        };

        expect(addImagesFromDesignArea(state)).toEqual({
            type: ADD_IMAGES_FROM_DESIGN_AREA,
            data: [
                {
                    fileName: '9c1330f774e4dada3c1bc8e2535143c3',
                    preview: {
                        url: '/img/uploads/designer/preview/9c1330f774e4dada3c1bc8e2535143c3.svg',
                    },
                },
            ],
        });
    });

    it('addGalleryImageToUserImages return the correct action', () => {
        const imageUrl = 'fakeImageUrl';
        const thumbUrl = 'fakeThumbUrl';
        const fileName = 'fakeFileName';
        const vectorizeColorsMap = {
            fakeColor: '#000000',
        };

        const dispatch = action => action;
        const getState = () => ({
            configurator: {
                configuration: {
                    designdata: {
                        designArea1: {
                            designProductionMethodIdentifier: 'customPrinting',
                        },
                    },
                },
            },
            designArea: {
                selectedDesignArea: {
                    identifier: 'designArea1',
                    mask: null,
                    designProductionMethods: [
                        {
                            identifier: 'customPrinting',
                            mask: null,
                            options: {
                                maxColorAmount: 4,
                                vectorsRequired: true,
                                vectorizedLogoMandatory: true,
                            },
                            colorPalettes: [
                                {
                                    identifier: 'default',
                                },
                            ],
                        },
                    ],
                },
            },
        });

        const action = addGalleryImageToUserImages(imageUrl, thumbUrl, fileName, vectorizeColorsMap, {
            width: 300,
            height: 150,
        })(dispatch, getState);

        expect(action).toEqual({
            type: ADD_GALLERY_IMAGE_TO_USER_IMAGES,
            fileName,
            imageUrl,
            thumbUrl,
            vectorizeColorsMap,
            compatibilityInfoHash: {
                maxColorAmount: 4,
                vectorizedLogoMandatory: true,
                vectorsRequired: true,
                colorPalettes: ['default'],
            },
            svgImageSize: { width: 300, height: 150 },
        });
    });

    it('setSelectedImageByIdentifier creates the correct action', () => {
        const correctAction = {
            type: SET_SELECTED_IMAGE,
            identifier: 'really-unique-image-identifier',
        };
        const result = setSelectedImageByIdentifier('really-unique-image-identifier');
        expect(result).toEqual(correctAction);
    });
});
