import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import React from 'react';
import { applyMiddleware, createStore } from 'redux';
import { persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
import promise from 'redux-promise-middleware';
import thunk from 'redux-thunk';
import { LOGGED_IN } from '../../constants/actionTypes';
import reducer from '../../reducers';
import getUIConfiguration from '../uiConfig';

const resources = require('./resources/NewlyAvailableEventsDialogue.resource.js');

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

describe.skip('NewlyAvailableEventsDialogueIntegrationTests', () => {
  it('callsGetAllEventsAndRefresh', (done) => {
    //mock the configuration file. Since mockGetUIConfiguration is out of scope of jest.mock(), it must start with 'mock'.
    const mockGetUIConfiguration = getUIConfiguration({
      EVENTS_PER_PAGE: 2,
      SORT_EVENTS_BY: 'creationDate',
      SORTING_ORDER: -1,
      AUTOREFRESH_EVENTLIST: false,
      AUTOREFRESH_DELAY: 100,
    });
    jest.mock('../../config/ui/config', () => mockGetUIConfiguration);

    // require logbook class after the configuration mocking
    const LogbookContainerClass = require('../../containers/Logbook/LogbookContainer')
      .LogbookContainer;
    LogbookContainerClass.prototype.getEventsBySelectionFilter = jest.fn(() =>
      Promise.resolve(resources.refreshEventList.serverResponse_No_Event)
    );
    LogbookContainerClass.prototype.getEventCountBySelectionFilter = jest.fn(
      () =>
        Promise.resolve(resources.refreshEventList.serverResponse_No_EventCount)
    );

    const mockedGetAllEventsAndRefresh = jest.spyOn(
      LogbookContainerClass.prototype,
      'getAllEventsAndRefresh'
    );

    const wrapper = getMountedWrapper();
    wrapper.update();
    expect(mockedGetAllEventsAndRefresh).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.
    LogbookContainerClass.prototype.getEventsBySelectionFilter.mockImplementation(
      () => Promise.resolve(resources.refreshEventList.serverResponse_One_Event)
    );
    LogbookContainerClass.prototype.getEventCountBySelectionFilter.mockImplementation(
      () =>
        Promise.resolve(
          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(mockedGetAllEventsAndRefresh).toHaveBeenCalledTimes(2);
      mockedGetAllEventsAndRefresh.mockRestore();
      done();
    }, 500);
  });

  it('refreshes the event list when the user clicks the icon', (done) => {
    //mock the configuration file. Since mockGetUIConfiguration is out of scope of jest.mock(), it must start with 'mock'.
    const mockGetUIConfiguration = getUIConfiguration({
      EVENTS_PER_PAGE: 2,
      SORT_EVENTS_BY: 'creationDate',
      SORTING_ORDER: -1,
      AUTOREFRESH_EVENTLIST: false,
      AUTOREFRESH_DELAY: 100,
    });
    jest.mock('../../config/ui/config', () => mockGetUIConfiguration);

    // require logbook class after the configuration mocking
    const LogbookContainerClass = require('../../containers/Logbook/LogbookContainer')
      .LogbookContainer;

    // start the logbook container, mock that one event is retrieved from the server
    LogbookContainerClass.prototype.getEventsBySelectionFilter = jest.fn(() =>
      Promise.resolve(resources.refreshEventList.serverResponse_One_Event)
    );
    LogbookContainerClass.prototype.getEventCountBySelectionFilter = jest.fn(
      () =>
        Promise.resolve(
          resources.refreshEventList.serverResponse_One_EventCount
        )
    );
    const wrapper = getMountedWrapper();

    setTimeout(() => {
      // after 200ms, the event list should have been rendered
      wrapper.update();
      expect(wrapper.find('Event')).toHaveLength(1);

      // Here we simulate that a new event was created. So the server returns 2 events
      LogbookContainerClass.prototype.getEventsBySelectionFilter.mockImplementation(
        () =>
          Promise.resolve(resources.refreshEventList.serverResponse_Two_Event)
      );
      LogbookContainerClass.prototype.getEventCountBySelectionFilter.mockImplementation(
        () =>
          Promise.resolve(
            resources.refreshEventList.serverResponse_Two_EventCount
          )
      );

      setTimeout(() => {
        // wait 500ms, it should be sufficient for the periodicRefresher to make the second call
        wrapper.update();
        wrapper
          .find('EventListMenu')
          .find('NewlyAvailableEventsDialogue')
          .find('Glyphicon')
          .simulate('click');

        setTimeout(() => {
          // after 200ms, the event list should have been rendered
          wrapper.update();

          expect(wrapper.find('Event')).toHaveLength(2);
          done();
        }, 200);
      }, 500);
    }, 200);
  });
});

/**
 * Get a mounted wrapper
 */
function getMountedWrapper() {
  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, promise(), thunk)
  );
  const LogbookContainer = require('../../containers/Logbook/LogbookContainer')
    .default;
  return Enzyme.mount(
    <LogbookContainer investigationId="testInvestigationId" />,
    { context: { store } }
  );
}
