'use strict';

import {
    selectDesignArea,
    actionTypes,
    toggleHighlight,
    setPreviousEditedDesignAreaIdentier,
    recalculateDesignArea,
} from '../Actions';
import designAreaReducer from '../Reducer';
import { RECEIVE_CONFIGURATION, receiveDesignerData } from '../../Configurator/Actions';
import { response, simpleState, simpleStateWithOutSelectedDesignArea } from '../__mocks__/designerData';
import {
    designViewsResponse,
    expectedBaseShape,
    expectedPosition,
    recalculateMockInitialState,
    recalculateMockInitialStateWithProd,
} from '../__mocks__/recalculateAreaData';

describe('Reducers/DesignArea', () => {
    test('designAreaReducer returns the correct initial state', () => {
        const initialState = designAreaReducer();
        expect(initialState).toEqual({
            filteredDesignAreas: [],
            selectedDesignArea: {},
            showHighlight: true,
            previousEditedDesignArea: {},
            initialCanvasPosition: [],
        });
    });
    test('designAreaReducer returns the correct state for RECEIVE_CONFIGURATION_MODES action', () => {
        const initialState = designAreaReducer();
        const configurationMode = {
            selectedMode: null,
            availableModes: {},
        };
        const action1 = receiveDesignerData()(
            v => v /* mock dispatch */,
            () => ({ configurator: {}, configurationMode }) /* mock getState */
        );
        // it returns the correct initial state
        expect(designAreaReducer(initialState, action1)).toEqual(initialState);
        const action2 = receiveDesignerData(response)(
            v => v /* mock dispatch */,
            () => ({ configurator: {}, configurationMode }) /* mock getState */
        );
        const state = designAreaReducer(initialState, action2);

        // it contains 2 design areas like the response
        expect(state.filteredDesignAreas.length).toBe(3);

        // the first filtered design area (sleeve) contains the data of the second designArea from the views
        // because it's linked with the selectedCameraView (see the line: 'customData': { selectedCameraView: '2' })
        expect(state.filteredDesignAreas[0].designView.identifier).toBe('1');

        // the second filtered design area (back) has the correct values from the response,
        // and has a reference to the containing design view
        expect(state.filteredDesignAreas[1].designView.identifier).toBe('2');

        // the third filtered design area (front) contains the data of the third designArea from the views
        // because it's linked with the defaultViewIdentifier
        expect(state.filteredDesignAreas[2].designView.identifier).toBe('3');

        // initially there is no selected design area
        expect(state.selectedDesignArea).toEqual({});
    });
    test('designAreaReducer returns the correct state for SELECT_DESIGN_AREA action for existing design area identifier', () => {
        const initialState = designAreaReducer(simpleState);
        const identifier = simpleState.filteredDesignAreas[1].identifier;
        const action = selectDesignArea(identifier);
        const state = designAreaReducer(initialState, action);
        expect(state.selectedDesignArea.identifier).toEqual(identifier);
    });
    test('designAreaReducer returns the previous state for SELECT_DESIGN_AREA action if the identifier does not exist', () => {
        const initialState = designAreaReducer(simpleState);
        const identifier = 'nonExistingAreaIdentifier';
        const action = selectDesignArea(identifier);
        const state = designAreaReducer(initialState, action);
        expect(state.selectedDesignArea).toEqual({ identifier: 'area2' });
    });
    test('designAreaReducer returns the correct state for CLEAR_DESIGN_AREA_SELECTION action', () => {
        const initialState = designAreaReducer(simpleState);
        const state = designAreaReducer(initialState, {
            type: actionTypes.CLEAR_DESIGN_AREA_SELECTION,
        });

        const initialState1 = designAreaReducer(simpleStateWithOutSelectedDesignArea);
        const state1 = designAreaReducer(initialState1, {
            type: actionTypes.CLEAR_DESIGN_AREA_SELECTION,
        });
        expect(state.selectedDesignArea).toEqual({});
        expect(state.lastSelectedDesignAreaIdentifier).toEqual('area2');
        expect(state.showHighlight).toEqual(true);
        expect(state1.lastSelectedDesignAreaIdentifier).toEqual('');
    });
    test('designAreaReducer returns the correct state for TOGGLE_HIGHLIGHT action', () => {
        const initialState = designAreaReducer(simpleState);
        const action = toggleHighlight(false);
        const state = designAreaReducer(initialState, action);
        expect(state.showHighlight).toEqual(false);
    });
    test('designAreaReducer returns the correct state for SET_PREVIOUS_EDITED_DESIGN_AREA action', () => {
        const initialState = designAreaReducer(simpleState);
        const identifier = simpleState.filteredDesignAreas[1].identifier;
        const action = setPreviousEditedDesignAreaIdentier(identifier);
        const state = designAreaReducer(initialState, action);
        expect(state.previousEditedDesignArea).toEqual({ identifier: identifier });
    });

    describe('recalculate area size and position', () => {
        test('recalculates when handling RECEIVE_CONFIGURATION_MODES', () => {
            const initialState = designAreaReducer();
            const action = receiveDesignerData(designViewsResponse)(
                v => v /* mock dispatch */,
                () => recalculateMockInitialStateWithProd /* mock getState */
            );
            const state = designAreaReducer(initialState, action);
            expect(state.filteredDesignAreas[0].position).toEqual(expectedPosition);
            expect(state.filteredDesignAreas[0].baseShape).toEqual(expectedBaseShape);
        });
        test('recalculates when handling RECALCULATE_DESIGN_AREA', () => {
            const initialState = designAreaReducer();
            const receiveConfigurationModesAction = receiveDesignerData(designViewsResponse)(
                v => v /* mock dispatch */,
                () => recalculateMockInitialState /* mock getState */
            );
            const currentState = designAreaReducer(initialState, receiveConfigurationModesAction);
            // the position should be the original, since there is no design production method selected
            expect(currentState.filteredDesignAreas[0].position).toEqual(
                designViewsResponse.designViews[0].designAreas[0].position
            );
            const action = recalculateDesignArea()(
                v => v /* mock dispatch */,
                () => recalculateMockInitialStateWithProd /* mock getState */
            );
            const state = designAreaReducer(currentState, action);
            expect(state.filteredDesignAreas[0].position).toEqual(expectedPosition);
            expect(state.filteredDesignAreas[0].baseShape).toEqual(expectedBaseShape);
        });
    });

    describe('configurationChangeReducer', () => {
        test('cleans up the design area related data on RECEIVE_CONFIGURATION action', () => {
            const filteredDesignAreas = [
                {
                    identifier: 'area_1',
                },
                {
                    identifier: 'area_2',
                },
            ];
            const initialState = {
                ...designAreaReducer(),
                filteredDesignAreas,
                selectedDesignArea: filteredDesignAreas[0],
                previousEditedDesignArea: filteredDesignAreas[0],
                initialCanvasPosition: [...filteredDesignAreas],
                showHighlight: false,
                otherProp: 'other props should not change',
            };
            const action = { type: RECEIVE_CONFIGURATION };
            const state = designAreaReducer(initialState, action);
            expect(state).toEqual({
                filteredDesignAreas: [],
                selectedDesignArea: {},
                previousEditedDesignArea: {},
                initialCanvasPosition: [],
                showHighlight: false, // should not change
                otherProp: 'other props should not change',
            });
        });
    });
});
