import {DashboardsContext} from '@bthlabs/homehub-core';
import {RangoAppContext} from '@bthlabs/rango';
import {mount} from 'enzyme';
import React from 'react';

import {
  AddDashboardModal, Taskbar, WidgetSettingsModal,
} from 'src/main/components';
import * as TaskbarContainer from 'src/main/containers/TaskbarContainer';

import {DashboardsContextFactory} from 'tests/__fixtures__/dashboardsContext';
import {
  FakeService, FakeServiceWithoutSettings, FakeWidget,
} from 'tests/__fixtures__/services';
import {SettingsFactory} from 'tests/__fixtures__/settings';

describe('src/main/containers/TaskbarContainer', () => {
  describe('TaskbarContainer', () => {
    let fakeDashboardsContext = null;
    let fakeSettings = null;
    let fakeRangoAppContext = null;

    beforeEach(() => {
      fakeDashboardsContext = DashboardsContextFactory();
      fakeSettings = SettingsFactory();
      fakeRangoAppContext = {settings: fakeSettings};
    });

    it('configures the WidgetSettingsModal to show settings view for added service', () => {
      // Given
      const component = mount(
        <RangoAppContext.Provider value={fakeRangoAppContext}>
          <DashboardsContext.Provider value={fakeDashboardsContext}>
            <TaskbarContainer.TaskbarContainer />
          </DashboardsContext.Provider>
        </RangoAppContext.Provider>
      );

      // When
      component.find(Taskbar).at(0).invoke('onAddService')(FakeService.kind);
      component.setProps({});

      // Then
      const widgetSettingsModal = component.find(WidgetSettingsModal).at(0);
      expect(widgetSettingsModal.prop('settingsView')).toEqual(
        FakeWidget.settingsView
      );
      expect(widgetSettingsModal.prop('settingsViewProps')).toEqual({
        nextCharacteristics: FakeService.emptyCharacteristics(),
        settings: fakeSettings,
        setNextCharacteristics: jasmine.any(Function),
      });
      expect(fakeDashboardsContext.addService).not.toHaveBeenCalled();
    });

    it('immediately adds a service that does not use settings view', () => {
      // Given
      const component = mount(
        <RangoAppContext.Provider value={fakeRangoAppContext}>
          <DashboardsContext.Provider value={fakeDashboardsContext}>
            <TaskbarContainer.TaskbarContainer />
          </DashboardsContext.Provider>
        </RangoAppContext.Provider>
      );

      // When
      component.find(Taskbar).at(0).invoke('onAddService')(
        FakeServiceWithoutSettings.kind
      );
      component.setProps({});

      // Then
      expect(fakeDashboardsContext.addService).toHaveBeenCalledWith(
        FakeServiceWithoutSettings.kind,
        FakeServiceWithoutSettings.emptyCharacteristics()
      );
    });

    it('handles the WidgetSettingsModal being closed', () => {
      // Given
      const component = mount(
        <RangoAppContext.Provider value={fakeRangoAppContext}>
          <DashboardsContext.Provider value={fakeDashboardsContext}>
            <TaskbarContainer.TaskbarContainer />
          </DashboardsContext.Provider>
        </RangoAppContext.Provider>
      );

      // When
      component.find(Taskbar).at(0).invoke('onAddService')(FakeService.kind);
      component.setProps({});

      component.find(WidgetSettingsModal).at(0).invoke('onClose')();
      component.setProps({});

      // Then
      const widgetSettingsModal = component.find(WidgetSettingsModal).at(0);
      expect(widgetSettingsModal.prop('settingsView')).toBe(null);
      expect(widgetSettingsModal.prop('settingsViewProps')).toEqual({});
    });

    it('handles the WidgetSettingsModal save button click', () => {
      // Given
      const component = mount(
        <RangoAppContext.Provider value={fakeRangoAppContext}>
          <DashboardsContext.Provider value={fakeDashboardsContext}>
            <TaskbarContainer.TaskbarContainer />
          </DashboardsContext.Provider>
        </RangoAppContext.Provider>
      );

      // When
      component.find(Taskbar).at(0).invoke('onAddService')(FakeService.kind);
      component.setProps({});

      component.find(WidgetSettingsModal).at(0).invoke('onSaveButtonClick')();
      component.setProps({});

      // Then
      expect(fakeDashboardsContext.addService).toHaveBeenCalledWith(
        FakeService.kind,
        FakeService.emptyCharacteristics()
      );
    });

    it('displays the AddDashboardModal when add dashboard button is clicked', () => {
      // Given
      const component = mount(
        <RangoAppContext.Provider value={fakeRangoAppContext}>
          <DashboardsContext.Provider value={fakeDashboardsContext}>
            <TaskbarContainer.TaskbarContainer />
          </DashboardsContext.Provider>
        </RangoAppContext.Provider>
      );

      // When
      component.find(Taskbar).at(0).invoke('onAddDashboard')();

      // Then
      const addDashboardModal = component.find(AddDashboardModal).at(0);
      expect(addDashboardModal.prop('show')).toBe(true);
    });

    it('hides the AddDashboardModal when it is closed', () => {
      // Given
      const component = mount(
        <RangoAppContext.Provider value={fakeRangoAppContext}>
          <DashboardsContext.Provider value={fakeDashboardsContext}>
            <TaskbarContainer.TaskbarContainer />
          </DashboardsContext.Provider>
        </RangoAppContext.Provider>
      );

      // When
      component.find(Taskbar).at(0).invoke('onAddDashboard')();
      component.find(AddDashboardModal).at(0).invoke('onClose')();

      // Then
      const addDashboardModal = component.find(AddDashboardModal).at(0);
      expect(addDashboardModal.prop('show')).toBe(false);
    });

    it('handles the AddDashboardModal save button click', () => {
      // Given
      const component = mount(
        <RangoAppContext.Provider value={fakeRangoAppContext}>
          <DashboardsContext.Provider value={fakeDashboardsContext}>
            <TaskbarContainer.TaskbarContainer />
          </DashboardsContext.Provider>
        </RangoAppContext.Provider>
      );

      // When
      component.find(AddDashboardModal).at(0).invoke('onSave')('Testing2');

      // Then
      expect(fakeDashboardsContext.addDashboard).toHaveBeenCalledWith(
        'Testing2'
      );
    });

    it('sets a selected dashboard as current', () => {
      // Given
      const component = mount(
        <RangoAppContext.Provider value={fakeRangoAppContext}>
          <DashboardsContext.Provider value={fakeDashboardsContext}>
            <TaskbarContainer.TaskbarContainer />
          </DashboardsContext.Provider>
        </RangoAppContext.Provider>
      );

      // When
      component.find(Taskbar).at(0).invoke('onSelectDashboard')('testing2');

      // Then
      expect(fakeDashboardsContext.setCurrentDashboardId).toHaveBeenCalledWith(
        'testing2'
      );
    });

    it('configures and renders the Taskbar', () => {
      // Given
      const component = mount(
        <RangoAppContext.Provider value={fakeRangoAppContext}>
          <DashboardsContext.Provider value={fakeDashboardsContext}>
            <TaskbarContainer.TaskbarContainer />
          </DashboardsContext.Provider>
        </RangoAppContext.Provider>
      );

      // When
      const taskbar = component.find(Taskbar).at(0);

      // Then
      expect(taskbar.exists()).toBe(true);
      expect(taskbar.prop('currentDashboardId')).toEqual(
        fakeDashboardsContext.currentDashboardId
      );
      expect(taskbar.prop('dashboards')).toEqual(
        fakeDashboardsContext.dashboards
      );
      expect(taskbar.prop('offlineMode')).toEqual(fakeSettings.OFFLINE_MODE);
      expect(taskbar.prop('savingState')).toEqual({
        isSaving: false,
        lastSaveError: null,
        lastSaveTimestamp: null,
      });
      expect(taskbar.prop('services')).toEqual(fakeSettings.SERVICES);
      expect(taskbar.prop('webSocketState')).toEqual({
        isWebSocketConnected: false,
      });
      expect(taskbar.prop('widgets')).toEqual(fakeSettings.WIDGETS);
    });

    it('configures and renders the WidgetSettingsModal', () => {
      // Given
      const component = mount(
        <RangoAppContext.Provider value={fakeRangoAppContext}>
          <DashboardsContext.Provider value={fakeDashboardsContext}>
            <TaskbarContainer.TaskbarContainer />
          </DashboardsContext.Provider>
        </RangoAppContext.Provider>
      );

      // When
      const widgetSettingsModal = component.find(WidgetSettingsModal).at(0);

      // Then
      expect(widgetSettingsModal.exists()).toBe(true);
      expect(widgetSettingsModal.prop('show')).toBe(true);
    });

    it('configures and renders the AddDashboardModal', () => {
      // Given
      const component = mount(
        <RangoAppContext.Provider value={fakeRangoAppContext}>
          <DashboardsContext.Provider value={fakeDashboardsContext}>
            <TaskbarContainer.TaskbarContainer />
          </DashboardsContext.Provider>
        </RangoAppContext.Provider>
      );

      // When
      const addDashboardModal = component.find(AddDashboardModal).at(0);

      // Then
      expect(addDashboardModal.exists()).toBe(true);
    });
  });
});
