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

import { Component } from '@angular/core';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { BrowserAnimationsModule, NoopAnimationsModule } from '@angular/platform-browser/animations';
import { RouterTestingModule } from '@angular/router/testing';
import { Observable, Subject } from 'rxjs';
import { BreadcrumbsService } from '../../core/breadcrumbs.service';
import { Breadcrumb } from './breadcrumb/breadcrumb.model';
import { BreadcrumbsComponent } from './breadcrumbs.component';
import { BreadcrumbComponent } from './breadcrumb/breadcrumb.component';


class BreadcrumbsFixtureComponentObject {
  private fixture;

  constructor(fixture: ComponentFixture<any>) {
    this.fixture = fixture;
  }

  getBreadcrumbs(): Element[] {
    return Array.from(this.fixture.nativeElement.querySelectorAll('* bci-breadcrumb'));
  }
}

@Component({
  template: `
    <bci-breadcrumbs role="navigation" aria-label="breadcrumbs">
      <bci-breadcrumb
        *ngFor="let breadcrumb of breadcrumbService.breadcrumbs | async"
        [title]="breadcrumb.title"
        [url]="breadcrumb.url"
      >
      </bci-breadcrumb>
    </bci-breadcrumbs>
  `,
})
class TestWrapperComponent {
  constructor(protected breadcrumbService: BreadcrumbsService) {}
}

describe('BreadcrumbsComponent', () => {
  let component: TestWrapperComponent;
  let fixture: ComponentFixture<TestWrapperComponent>;
  let co: BreadcrumbsFixtureComponentObject;
  const breadcrumb$ = new Subject<Breadcrumb[]>();

  beforeEach(
    waitForAsync(() => {
      const breadcrumbObservable: Observable<Breadcrumb[]> = breadcrumb$.asObservable();
      const breadcrumbServiceMock = {
        breadcrumbs: breadcrumbObservable,
      };
      TestBed.configureTestingModule({
        imports: [RouterTestingModule, BrowserAnimationsModule, NoopAnimationsModule ],
        providers: [{ provide: BreadcrumbsService, useValue: breadcrumbServiceMock }],
        declarations: [TestWrapperComponent, BreadcrumbsComponent, BreadcrumbComponent],
      }).compileComponents();
    })
  );

  beforeEach(() => {
    fixture = TestBed.createComponent(TestWrapperComponent);
    component = fixture.componentInstance;
    co = new BreadcrumbsFixtureComponentObject(fixture);
    fixture.detectChanges();
  });

  it(
    'should create',
    waitForAsync(() => {
      expect(component).toBeTruthy();
      // 'breadcrumbs list initially empty'
      expect(co.getBreadcrumbs().length).toEqual(0);
    })
  );

  it(
    'should react to new breadcrumbs',
    waitForAsync(() => {
      breadcrumb$.next([{ url: 'a', title: 'A' }]);
      fixture.detectChanges();
      // 'breadcrumbs list reflects current breadcrumbs from serivce'
      expect(co.getBreadcrumbs().map((el) => el.textContent.trim())).toEqual(['A']);
    })
  );

  it(
    'should show three breadcrumbs',
    waitForAsync(() => {
      breadcrumb$.next([
        { url: 'a', title: 'A' },
        { url: 'b', title: 'B' },
        { url: 'c', title: 'C' },
      ]);
      fixture.detectChanges();
      expect(co.getBreadcrumbs().map((el) => el.textContent.trim())).toEqual(['A', 'B', 'C']);
    })
  );

  it(
    'should replace surplus intermediate breadcrumbs using ellipsis and add element title instead',
    waitForAsync(() => {
      fixture.autoDetectChanges();
      breadcrumb$.next([
        { url: 'a', title: 'A' },
        { url: 'b', title: 'B' },
        { url: 'c', title: 'C' },
        {
          url: 'd',
          title: 'D',
        },
      ]);
      fixture.detectChanges();
      fixture.detectChanges();
      fixture.whenStable().then(() => {
        expect(co.getBreadcrumbs().map((el) => el.textContent.trim())).toEqual(['A', '…', 'C', 'D']);
        expect(co.getBreadcrumbs().map((el) => el.getAttribute('title'))).toEqual([null, 'B', null, null]);
      });
    })
  );
});
