/*
 * Copyright (C) 2018 Robert Bosch GmbH Copyright (C) 2018 Robert Bosch Manufacturing Solutions GmbH, Germany. All rights reserved.
 */

import { ComponentFixture, TestBed, tick, waitForAsync } from '@angular/core/testing';
import { MatIconModule } from '@angular/material/icon';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { ActivatedRoute, Params } from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing';
import { BciSharedModule, BreadcrumbsService, MasterDetailViewComponent } from '@bci-web-core/core';
import { LocationMapModule, LocationMapService, LocationService } from '@bci-web-core/maps';
import { BehaviorSubject, of } from 'rxjs';
import { delay, map } from 'rxjs/operators';
import { LocationServiceMock } from '../location-service-mock.service';
import { LocationFormComponent } from './location-form.component';

describe('LocationFormComponent', () => {
  const masterDetailViewStub: Partial<MasterDetailViewComponent> = {
    openDetails: jest.fn(),
    closeDetails: jest.fn().mockImplementation(() =>
      of(true).pipe(
        delay(1000),
        map(() => undefined)
      )
    ),
  };
  const breadcrumbServiceMock: Partial<BreadcrumbsService> = {
    setTemporaryTitleForRoute: jest.fn(),
  };
  const activatedRouteMock: Partial<ActivatedRoute> = {
    params: new BehaviorSubject<Params>({ id: '1' }),
  };

  let component: LocationFormComponent;
  let fixture: ComponentFixture<LocationFormComponent>;
  
  /* eslint-disable-next-line @typescript-eslint/no-unused-vars */
  let locationService: LocationService;
  let locationMapService: LocationMapService;

  beforeEach(
    waitForAsync(() => {
      return TestBed.configureTestingModule({
        imports: [
          NoopAnimationsModule,
          BciSharedModule,
          RouterTestingModule,
          MatIconModule,
          LocationMapModule,
          MatSnackBarModule,
        ],
        providers: [
          { provide: MasterDetailViewComponent, useValue: masterDetailViewStub },
          { provide: LocationService, useClass: LocationServiceMock },
          { provide: BreadcrumbsService, useValue: breadcrumbServiceMock },
          { provide: ActivatedRoute, useValue: activatedRouteMock },
          LocationMapService,
        ],
        declarations: [LocationFormComponent],
      }).compileComponents();
    })
  );

  beforeEach(() => {
    fixture = TestBed.createComponent(LocationFormComponent);
    locationService = TestBed.inject(LocationService);
    locationMapService = TestBed.inject(LocationMapService);
    component = fixture.componentInstance;
    component['masterDetailView'] = <any>masterDetailViewStub;
  });

  afterEach(() => {
    fixture.destroy();
  });

  it(
    'should create',
    waitForAsync(() => {
      expect(component).toBeTruthy();
    })
  );

  it(
    'should clear form upon parameter change',
    fakewaitForAsync(() => {
      component.ngOnInit();
      tick(2000);
      expect(component.location).not.toBeUndefined();

      (activatedRouteMock.params as BehaviorSubject<Params>).next({ id: '5' });
      tick(100);
      // form should empty while loading
      expect(component.location).toBeUndefined();

      tick(2000);
      expect(component.location).not.toBeUndefined();
    })
  );

  it(
    'should set desired location and open details once loaded',
    fakewaitForAsync(() => {
      component.ngOnInit();
      tick(2000);
      expect(component.location).not.toBeUndefined();
      expect(masterDetailViewStub.openDetails).toHaveBeenCalled();
    })
  );

  it(
    'should set loaded location as selection',
    fakewaitForAsync(() => {
      component.ngOnInit();
      tick(2000);
      expect(component.location).not.toBeUndefined();
      expect(locationMapService.selectedLocations).toEqual([component.location]);
    })
  );

  it(
    'should set breadcrumb for loaded location',
    fakewaitForAsync(() => {
      component.ngOnInit();
      tick(2000);
      expect(component.location).not.toBeUndefined();
      expect(breadcrumbServiceMock.setTemporaryTitleForRoute).toHaveBeenCalled();
    })
  );

  it(
    'should close details and clear selection when destroyed',
    fakewaitForAsync(() => {
      component.ngOnInit();
      tick(2000);
      component.ngOnDestroy();
      tick(2000);
      expect(masterDetailViewStub.closeDetails).toHaveBeenCalled();
      expect(locationMapService.selectedLocations).toEqual([]);
    })
  );

  it(
    'should clear selection when closed',
    fakewaitForAsync(() => {
      component.ngOnInit();
      tick(2000);
      component.closeDetails();
      expect(locationMapService.selectedLocations).not.toEqual([]);
      tick(2000);
      expect(locationMapService.selectedLocations).toEqual([]);
    })
  );
});
