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

import { Component, DebugElement } from '@angular/core';
import {
  ComponentFixture,
  fakeAsync,
  TestBed,
  tick,
  waitForAsync,
} from '@angular/core/testing';
import { MatBadgeModule } from '@angular/material/badge';
import { MatIconModule } from '@angular/material/icon';
import { MatMenuModule } from '@angular/material/menu';
import { MatTooltipModule } from '@angular/material/tooltip';
import { By } from '@angular/platform-browser';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { BCI_SHARED_INTL_PROVIDER } from '../../shared-intl';
import { CommandbarButtonComponent } from '../button/commandbar-button.component';
import { CommandbarItemVisibilityService } from '../item/commandbar-item-visibility.service';
import { CommandbarItemComponent } from '../item/commandbar-item.component';
import { CommandbarActionsComponent } from './actions.component';

@Component({
  template: ` <bci-commandbar-actions>
    <bci-commandbar-button [icon]="iconButtonA" hide="lt-md">labelA</bci-commandbar-button>
    <bci-commandbar-item hide="lt-lg" #myItem>
      <mat-icon [fontIcon]="iconButtonB"></mat-icon>
      <span *ngIf="myItem.renderLargeVariant">labelB</span></bci-commandbar-item
    >
    <bci-commandbar-button [icon]="iconButtonC" hide="lt-xl">labelC</bci-commandbar-button>
    <bci-commandbar-item *ngIf="showConditionalItem">
      <mat-icon [fontIcon]="iconButtonD"></mat-icon>
      <span>labelD</span></bci-commandbar-item
    >
  </bci-commandbar-actions>`,
})
class TestComponent {
  showConditionalItem = false;
  readonly iconButtonA = 'Bosch-Ic-add';
  readonly iconButtonB = 'Bosch-Ic-edit';
  readonly iconButtonC = 'Bosch-Ic-delete';
  readonly iconButtonD = 'Bosch-Ic-sort';
  readonly icons = [this.iconButtonA, this.iconButtonB, this.iconButtonC, this.iconButtonD];
}

describe('CommandbarActionsComponent', () => {
  let fixture: ComponentFixture<TestComponent>;
  let testComponent: TestComponent;
  let component: CommandbarActionsComponent;
  let debugElement: DebugElement;

  beforeEach(
    waitForAsync(() => {
      TestBed.configureTestingModule({
        imports: [
          MatMenuModule,
          MatIconModule,
          NoopAnimationsModule,
          MatTooltipModule,
          MatBadgeModule,
        ],
        declarations: [TestComponent, CommandbarActionsComponent, CommandbarItemComponent, CommandbarButtonComponent],
        providers: [BCI_SHARED_INTL_PROVIDER, CommandbarItemVisibilityService],
      }).compileComponents();
    })
  );

  beforeEach(
    waitForAsync(() => {
      fixture = TestBed.createComponent(TestComponent);
      fixture.detectChanges();

      testComponent = fixture.componentInstance;
      debugElement = fixture.debugElement.query(By.css('bci-commandbar-actions'));
      component = debugElement.injector.get(CommandbarActionsComponent);

      component.ngAfterViewInit();
      fixture.detectChanges();
    })
  );

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

  describe('reactive more-menu behavior', () => {
    it(
      'should hide lt-lg and lt-xl when md',
      waitForAsync(() => {
        expect(component.visibleItems.length).toBe(3);
        expect(component.hiddenItems.length).toBe(0);
      })
    );

    it('should be able to hide everything', fakeAsync(() => {
      component.updateView(0);
      component.updateView(0);
      component.updateView(0);
      expect(component.visibleItems.length).toBe(0);
      expect(component.hiddenItems.length).toBe(3);
    }));

    it('should not hide single hidden item', fakeAsync(() => {
      tick(100);
      fixture.detectChanges();

      // displaying a more action button for one action does not make sense
      expect(component.visibleItems.length).toBe(3);
      expect(component.hiddenItems.length).toBe(0);
    }));

    it('should react to window resizing', fakeAsync(() => {
      expect(component.visibleItems.length).toBe(3);
      expect(component.hiddenItems.length).toBe(0);

      component.updateView(0);
      tick(100);

      expect(component.visibleItems.length).toBe(2);
      expect(component.hiddenItems.length).toBe(1);
      fixture.detectChanges();
    }));

    it('should react to window resizing and not loose any actions', fakeAsync(() => {
      expect(component.visibleItems.length).toBe(3);
      expect(component.hiddenItems.length).toBe(0);
      fixture.detectChanges();

      // simulate window resizing
      component.updateView(0);
      fixture.detectChanges();

      // make labels show up in inlined actions
      component.renderLargeInlinedItemVariants = true;
      fixture.detectChanges();

      expect(component.visibleItems.length).toBe(2);
      expect(component.hiddenItems.length).toBe(1);

      // simulate window resizing
      component.updateView(100);
      fixture.detectChanges();

      expect(component.visibleItems.length).toBe(3);
      expect(component.hiddenItems.length).toBe(0);
    }));
  });

  it('should react to item changes', fakeAsync(() => {
    expect(component.visibleItems.length).toBe(3);
    expect(component.hiddenItems.length).toBe(0);

    testComponent.showConditionalItem = true;
    fixture.detectChanges();
    tick(100);

    expect(component.visibleItems.length).toBe(4);
    expect(component.hiddenItems.length).toBe(0);
  }));

  describe('action label rendering', () => {
    it('should be able to show labels in commandbar', fakeAsync(() => {
      expect(component.visibleItems.length).toBe(3);
      expect(component.hiddenItems.length).toBe(0);
      fixture.detectChanges();

      component.renderLargeInlinedItemVariants = true;
      fixture.detectChanges();

      // simulate window resizing
      fixture.detectChanges();

      expect(component.visibleItems.length).toBe(3);
      expect(component.hiddenItems.length).toBe(0);
      component.visibleItems.forEach((item) => expect(item.renderLargeVariant).toBeTruthy());
    }));
  });
});
