import {shallow} from 'enzyme';
import React from 'react';

import {StartMenu} from 'src/main/components/StartMenu';
import * as Taskbar from 'src/main/components/Taskbar';
import {SERVICES} from 'src/services';
import {WIDGETS} from 'src/widgets';

import {DashboardsFactory} from 'tests/__fixtures__/dashboards';

describe('src/main/components/Taskbar', () => {
  describe('Taskbar', () => {
    let mockOnAddDashboard = null;
    let mockOnAddService = null;
    let mockOnSelectDashboard = null;
    let fakeDashboards = null;
    let fakeSavingState = null;
    let fakeWebSocketState = null;

    beforeEach(() => {
      mockOnAddDashboard = jasmine.createSpy();
      mockOnAddService = jasmine.createSpy();
      mockOnSelectDashboard = jasmine.createSpy();
      fakeDashboards = DashboardsFactory();
      fakeSavingState = {
        isSaving: false,
        lastSaveError: null,
        lastSaveTimestamp: new Date(1987, 9, 3, 8, 0, 0),
      };
      fakeWebSocketState = {
        isWebSocketConnected: true,
      };
    });

    it('configures and renders the start menu', () => {
      // Given
      const component = shallow(
        <Taskbar.Taskbar
          currentDashboardId="testing"
          dashboards={fakeDashboards}
          offlineMode={false}
          savingState={fakeSavingState}
          services={SERVICES}
          webSocketState={fakeWebSocketState}
          widgets={WIDGETS}
          onAddDashboard={mockOnAddDashboard}
          onAddService={mockOnAddService}
        />
      );

      // When
      const startMenu = component.find(StartMenu).at(0);

      // Then
      expect(startMenu.exists()).toBe(true);
      expect(startMenu.prop('offlineMode')).toBe(false);
      expect(startMenu.prop('services')).toEqual(SERVICES);
      expect(startMenu.prop('widgets')).toEqual(WIDGETS);
      expect(startMenu.prop('onAddDashboard')).toEqual(mockOnAddDashboard);
      expect(startMenu.prop('onAddService')).toEqual(mockOnAddService);
    });

    it('configures renders the dashboard buttons', () => {
      // Given
      const component = shallow(
        <Taskbar.Taskbar
          currentDashboardId="testing"
          dashboards={fakeDashboards}
          offlineMode={false}
          savingState={fakeSavingState}
          services={SERVICES}
          webSocketState={fakeWebSocketState}
          widgets={WIDGETS}
          onAddDashboard={mockOnAddDashboard}
          onAddService={mockOnAddService}
        />
      );

      // When
      const dashboardButtons = component.find('a[_hint="Dashboard"]');

      // Then
      expect(dashboardButtons.length).toEqual(2);

      const dashboardButton = dashboardButtons.at(0);
      expect(dashboardButton.hasClass('active')).toBe(true);
      expect(dashboardButton.prop('data-dashboard')).toEqual(
        fakeDashboards[0].id
      );
      expect(dashboardButton.text()).toEqual(fakeDashboards[0].name);

      expect(dashboardButtons.at(1).hasClass('active')).toBe(false);
    });

    it('selects a dashboard when its button is clicked', () => {
      // Given
      const component = shallow(
        <Taskbar.Taskbar
          currentDashboardId="testing"
          dashboards={fakeDashboards}
          offlineMode={false}
          savingState={fakeSavingState}
          services={SERVICES}
          webSocketState={fakeWebSocketState}
          widgets={WIDGETS}
          onAddDashboard={mockOnAddDashboard}
          onAddService={mockOnAddService}
          onSelectDashboard={mockOnSelectDashboard}
        />
      );

      // When
      component.find('a[_hint="Dashboard"]').at(0).simulate('click', {
        currentTarget: {
          dataset: {dashboard: fakeDashboards[0].id},
        },
      });

      // Then
      expect(mockOnSelectDashboard).toHaveBeenCalledWith(fakeDashboards[0].id);
    });

    it('does not render websocket status in offline mode', () => {
      // Given
      const component = shallow(
        <Taskbar.Taskbar
          currentDashboardId="testing"
          dashboards={fakeDashboards}
          offlineMode={true}
          savingState={fakeSavingState}
          services={SERVICES}
          webSocketState={fakeWebSocketState}
          widgets={WIDGETS}
          onAddDashboard={mockOnAddDashboard}
          onAddService={mockOnAddService}
          onSelectDashboard={mockOnSelectDashboard}
        />
      );

      // Then
      expect(component.find('Icon[_hint="WebSocketConnected"]').exists()).toBe(
        false
      );
      expect(component.find('Icon[_hint="WebSocketNotConnected"]').exists()).toBe(
        false
      );
    });

    it('renders the websocket connection status when websocket is connected', () => {
      // Given
      const component = shallow(
        <Taskbar.Taskbar
          currentDashboardId="testing"
          dashboards={fakeDashboards}
          offlineMode={false}
          savingState={fakeSavingState}
          services={SERVICES}
          webSocketState={fakeWebSocketState}
          widgets={WIDGETS}
          onAddDashboard={mockOnAddDashboard}
          onAddService={mockOnAddService}
          onSelectDashboard={mockOnSelectDashboard}
        />
      );

      // Then
      expect(component.find('Icon[_hint="WebSocketConnected"]').exists()).toBe(
        true
      );
      expect(component.find('Icon[_hint="WebSocketNotConnected"]').exists()).toBe(
        false
      );
    });

    it('renders the websocket connection status when websocket is not connected', () => {
      // Given
      fakeWebSocketState.isWebSocketConnected = false;
      const component = shallow(
        <Taskbar.Taskbar
          currentDashboardId="testing"
          dashboards={fakeDashboards}
          offlineMode={false}
          savingState={fakeSavingState}
          services={SERVICES}
          webSocketState={fakeWebSocketState}
          widgets={WIDGETS}
          onAddDashboard={mockOnAddDashboard}
          onAddService={mockOnAddService}
          onSelectDashboard={mockOnSelectDashboard}
        />
      );

      // Then
      expect(component.find('Icon[_hint="WebSocketConnected"]').exists()).toBe(
        false
      );
      expect(component.find('Icon[_hint="WebSocketNotConnected"]').exists()).toBe(
        true
      );
    });

    it('renders the saving status when it is saving', () => {
      // Given
      fakeSavingState.isSaving = true;
      const component = shallow(
        <Taskbar.Taskbar
          currentDashboardId="testing"
          dashboards={fakeDashboards}
          offlineMode={false}
          savingState={fakeSavingState}
          services={SERVICES}
          webSocketState={fakeWebSocketState}
          widgets={WIDGETS}
          onAddDashboard={mockOnAddDashboard}
          onAddService={mockOnAddService}
          onSelectDashboard={mockOnSelectDashboard}
        />
      );

      // Then
      expect(component.find('Icon[_hint="IsSaving"]').exists()).toBe(true);
      expect(component.find('Icon[_hint="SaveError"]').exists()).toBe(false);
      expect(component.find('Icon[_hint="SaveOK"]').exists()).toBe(false);
    });

    it('renders the saving status when last save was an error', () => {
      // Given
      fakeSavingState.lastSaveError = 'FIAL';
      const component = shallow(
        <Taskbar.Taskbar
          currentDashboardId="testing"
          dashboards={fakeDashboards}
          offlineMode={false}
          savingState={fakeSavingState}
          services={SERVICES}
          webSocketState={fakeWebSocketState}
          widgets={WIDGETS}
          onAddDashboard={mockOnAddDashboard}
          onAddService={mockOnAddService}
          onSelectDashboard={mockOnSelectDashboard}
        />
      );

      // Then
      expect(component.find('Icon[_hint="IsSaving"]').exists()).toBe(false);
      expect(component.find('Icon[_hint="SaveError"]').exists()).toBe(true);
      expect(component.find('Icon[_hint="SaveOK"]').exists()).toBe(false);
    });

    it('renders the saving status when last save was OK', () => {
      // Given
      const component = shallow(
        <Taskbar.Taskbar
          currentDashboardId="testing"
          dashboards={fakeDashboards}
          offlineMode={false}
          savingState={fakeSavingState}
          services={SERVICES}
          webSocketState={fakeWebSocketState}
          widgets={WIDGETS}
          onAddDashboard={mockOnAddDashboard}
          onAddService={mockOnAddService}
          onSelectDashboard={mockOnSelectDashboard}
        />
      );

      // Then
      expect(component.find('Icon[_hint="IsSaving"]').exists()).toBe(false);
      expect(component.find('Icon[_hint="SaveError"]').exists()).toBe(false);
      expect(component.find('Icon[_hint="SaveOK"]').exists()).toBe(true);
    });
  });
});
