import React from 'react';
import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import { createStore, applyMiddleware } from 'redux';
import { persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
import logger from 'redux-logger';
import thunk from 'redux-thunk';
import reducer from '../../src/reducers';
import promise from "redux-promise-middleware";
import { LOGGED_IN } from '../../src/constants/ActionTypes';
import { GUI_CONFIG } from '../../src/config/gui.config';
jest.mock("../../src/config/gui.config");
import LogbookContainer, { LogbookContainer as LogbookContainerNoConnect } from '../../src/containers/Logbook/LogbookContainer';

const IORequestModule = require('../../src/containers/Logbook/IORequests')
const resources = require('./resources/NewlyAvailableEventsDialogue.resource.js');

beforeEach(() => {
    Enzyme.configure({ adapter: new Adapter() })
})

describe("NewlyAvailableEventsDialogue integration tests", () => {
    // mock and reimplement getTagsByInvestigationId()
    IORequestModule.getTagsByInvestigationId = jest.fn((sessionId, investigationId, onSuccess, onError) => {
        onSuccess({ data: [] });
    });
    function getWrapper() {
        /* overrides default configuration */
        GUI_CONFIG.mockReturnValue({
            EVENTS_PER_PAGE: 2,
            DEFAULT_SORTING_FILTER: {
                createdAt: -1  // temporary workaround. createdAt must be replaced by creationDate
            },
            AUTOREFRESH_ENABLED: true,
            AUTOREFRESH_DELAY: 100,
            AUTOREFRESH_EVENTLIST: false
        })

        const middleware = [thunk];
        const persistConfig = { key: 'root', storage }
        const persistedReducer = persistReducer(persistConfig, reducer)
        const store = createStore(
            persistedReducer,
            { user: { type: LOGGED_IN, username: 'username', sessionId: 'testSessionId' } },
            applyMiddleware(...middleware, logger, promise(), thunk)
        )

        return Enzyme.mount(<LogbookContainer investigationId="testInvestigationId" />, { context: { store } })
    };

    it('calls getEvents when the user clicks the refresh icon on the NewlyAvailableEventsDialogue', (done) => {
        IORequestModule.getEventsByInvestigationId = jest.fn((sessionId, investigationId, limit, offset, selectionFilter, sortingFilter, onSuccess, onError) => {
            onSuccess(resources.refreshEventList.serverResponse_No_Event);
        });
        IORequestModule.getEventCountByInvestigationId = jest.fn((investigationId, sessionId, selectionFilter, onSuccess, onEventsReceptionFailure) => {
            onSuccess(resources.refreshEventList.serverResponse_No_EventCount);
        });
        const mockedGetEvents = jest.spyOn(LogbookContainerNoConnect.prototype, 'getEvents');
        const wrapper = getWrapper();

        wrapper.update();
        expect(mockedGetEvents).toHaveBeenCalledTimes(1); //called by component will mount

        // change the mock functions to simulate that another event was created in the mean time. This is required so that the refresh glyphicon is rendered.
        IORequestModule.getEventsByInvestigationId = jest.fn((sessionId, investigationId, limit, offset, selectionFilter, sortingFilter, onSuccess, onError) => {
            onSuccess(resources.refreshEventList.serverResponse_One_Event);
        });
        IORequestModule.getEventCountByInvestigationId = jest.fn((investigationId, sessionId, selectionFilter, onSuccess, onEventsReceptionFailure) => {
            onSuccess(resources.refreshEventList.serverResponse_One_EventCount);
        });
        // wait 500ms, it should be sufficient for the periodicRefresher to make the second call
        setTimeout(() => {
            wrapper.update()
            wrapper.find('EventListMenu').find('NewlyAvailableEventsDialogue').find('Glyphicon').simulate('click');
            expect(mockedGetEvents).toHaveBeenCalledTimes(2);
            mockedGetEvents.mockRestore();
            done()
        }, 500);
    })

    it('refreshes the event list when the user clicks the refresh icon on the NewlyAvailableEventsDialogue', () => {
        IORequestModule.getEventsByInvestigationId = jest.fn((sessionId, investigationId, limit, offset, selectionFilter, sortingFilter, onSuccess, onError) => {
            onSuccess(resources.refreshEventList.serverResponse_One_Event);
        });
        IORequestModule.getEventCountByInvestigationId = jest.fn((investigationId, sessionId, selectionFilter, onSuccess, onEventsReceptionFailure) => {
            onSuccess(resources.refreshEventList.serverResponse_One_EventCount);
        });

        const wrapper = getWrapper();
        wrapper.update();

        // Initialisation of the container. There is one event in the event list returned by the server
        expect(wrapper.find('Event')).toHaveLength(1);

        // Here we simulate that a new event was created. So the server returns 2 events
        IORequestModule.getEventsByInvestigationId = jest.fn((sessionId, investigationId, limit, offset, selectionFilter, sortingFilter, onSuccess, onError) => {
            onSuccess(resources.refreshEventList.serverResponse_Two_Event)
        });
        IORequestModule.getEventCountByInvestigationId = jest.fn((investigationId, sessionId, selectionFilter, onSuccess, onEventsReceptionFailure) => {
            onSuccess(resources.refreshEventList.serverResponse_Two_EventCount)
        });

        // wait 500ms, it should be sufficient for the periodicRefresher to make the second call
        setTimeout(() => {
            wrapper.update();
            // Simulate a click on the refresh glyphicon
            wrapper.find('EventListMenu').find('NewlyAvailableEventsDialogue').find('Glyphicon').simulate('click');
            expect(wrapper.find('Event')).toHaveLength(2);
        },
            500);
    })
});