import * as HomeHubCore from '@bthlabs/homehub-core';

import * as IFormicariumService from 'src/IFormicariumService';

import {IFormicariumDataFactory} from 'tests/__fixtures__/iformicarium';

describe('src/IFormicariumService', () => {
  describe('IFormicariumService', () => {
    let fakeCharacteristics = null;
    let fakeResult = null;

    beforeEach(() => {
      fakeCharacteristics = {
        mqtt: 'thisisntright.local',
        name: 'iformicarium',
        topic: 'iformicarium',
      };
      fakeResult = IFormicariumDataFactory();

      spyOn(HomeHubCore.API.Services, 'start').and.returnValue(fakeResult);
      spyOn(HomeHubCore.API.Services, 'stop').and.returnValue('ok');
    });

    describe('emptyCharacteristics', () => {
      it('returns empty characteristics', () => {
        // Given
        const result = IFormicariumService.IFormicariumService.emptyCharacteristics();

        // Then
        expect(result).toEqual({
          name: '',
          mqtt: '',
          topic: 'iformicarium',
        });
      });
    });

    describe('start', () => {
      it('notifies subscribers with the result of start service API call', async () => {
        // Given
        const service = new IFormicariumService.IFormicariumService({
          instance: 'testing',
          characteristics: fakeCharacteristics,
        });
        spyOn(service, 'notify');

        // When
        await service.start();

        // Then
        expect(HomeHubCore.API.Services.start).toHaveBeenCalledWith(
          service.kind, 'testing', fakeCharacteristics
        );
        expect(service.notify).toHaveBeenCalledWith(fakeResult);
      });
    });

    describe('stop', () => {
      it('calls the stop service API method', async () => {
        // Given
        const service = new IFormicariumService.IFormicariumService({
          instance: 'testing',
          characteristics: fakeCharacteristics,
        });

        // When
        await service.stop();

        // Then
        expect(HomeHubCore.API.Services.stop).toHaveBeenCalledWith(
          service.kind, 'testing'
        );
      });
    });

    describe('setCharacteristics', () => {
      it('updates the service characteristics', () => {
        // Given
        const newCharacteristics = {
          mqtt: 'thisisntrighttoo.local',
          name: 'iformicarium2',
          topic: 'iformicarium2',
        };
        const service = new IFormicariumService.IFormicariumService({
          instance: 'testing',
          characteristics: fakeCharacteristics,
        });
        spyOn(service, 'restart');

        // When
        service.setCharacteristics(newCharacteristics);

        // Then
        expect(service.characteristics).toEqual(newCharacteristics);
      });

      it('restarts the service if mqtt characteristic changed', () => {
        // Given
        const newCharacteristics = {
          ...fakeCharacteristics,
          mqtt: 'thisisntrighttoo.local',
        };
        const service = new IFormicariumService.IFormicariumService({
          instance: 'testing',
          characteristics: fakeCharacteristics,
        });
        spyOn(service, 'restart');

        // When
        service.setCharacteristics(newCharacteristics);

        // Then
        expect(service.restart).toHaveBeenCalled();
      });

      it('restarts the service if name characteristic changed', () => {
        // Given
        const newCharacteristics = {
          ...fakeCharacteristics,
          name: 'iformicarium2',
        };
        const service = new IFormicariumService.IFormicariumService({
          instance: 'testing',
          characteristics: fakeCharacteristics,
        });
        spyOn(service, 'restart');

        // When
        service.setCharacteristics(newCharacteristics);

        // Then
        expect(service.restart).toHaveBeenCalled();
      });

      it('restarts the service if topic characteristic changed', () => {
        // Given
        const newCharacteristics = {
          ...fakeCharacteristics,
          topic: 'iformicarium2',
        };
        const service = new IFormicariumService.IFormicariumService({
          instance: 'testing',
          characteristics: fakeCharacteristics,
        });
        spyOn(service, 'restart');

        // When
        service.setCharacteristics(newCharacteristics);

        // Then
        expect(service.restart).toHaveBeenCalled();
      });
    });
  });
});
