/*
 * Copyright (C) 2018 Robert Bosch GmbH Copyright (C) 2018 Robert Bosch Manufacturing Solutions GmbH, Germany. All rights reserved.
 */
/* eslint-disable @typescript-eslint/no-empty-function */

import { Component, Injectable, NgModule, NO_ERRORS_SCHEMA } from '@angular/core';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { AlertService } from '@bci-web-core/core';
import { of } from 'rxjs';
import { Widget } from '..';
import { CatalogConf } from '../models/catalog-conf';
import { WidgetTypes } from '../models/definitions';
import { WidgetDefinition } from '../models/widget-definition';
import { PinboardModule } from '../pinboard.module';
import { WidgetDefinitionService } from '../services/widget-definition.service';
import { PinboardInteractionService } from './../services/pinboard-interaction.service';
import { TestTextContentComponent, TestTextWidgetUserSetting } from './test-text-widget-component';
import { WidgetComponent } from './widget.component';

@Injectable()
export class PinboardInteractionServiceMock {
  pinboardGridComponent = {
    checkForWidgetCollision: () => {
      return false;
    },
    resizeWidgets: () => {},
    updateGrid: () => {},
    gridsterOptions: {
      draggable: {
        enabled: true,
      },
    },
  };
}

@Injectable()
export class AlertServiceMock {
  // When the component calls this.dialog.open(...) we'll return an object
  // with an afterClosed method that allows to subscribe to the dialog result observable.
  openAlertBox() {
    return {
      afterClosed: () => of('left'),
    };
  }
}

@Component({
  selector: 'bci-test-widget-cmp',
  template: ` <bci-widget [widget]="w"></bci-widget>`,
})
class TestWrapperComponent {
  public w: Widget;

  constructor() {
    this.w = new Widget('test');
    this.w.widgetDefinition = new WidgetDefinition<any, TestTextWidgetUserSetting, any>(
      'def',
      {} as CatalogConf,
      'TextWidget'
    );
  }
}

@NgModule({
  imports: [NoopAnimationsModule, PinboardModule],
  providers: [
    { provide: PinboardInteractionService, useClass: PinboardInteractionServiceMock },
    WidgetDefinitionService,
    {
      provide: AlertService,
      useClass: AlertServiceMock,
    },
  ],
  declarations: [TestWrapperComponent, TestTextContentComponent],
  schemas: [NO_ERRORS_SCHEMA],
})
export class TestWrapperModule {}

describe('WidgetComponent', () => {
  let component: WidgetComponent;
  let fixture: ComponentFixture<TestWrapperComponent>;
  let dialog: AlertService;

  beforeEach(
    waitForAsync(() => {
      TestBed.configureTestingModule({
        imports: [TestWrapperModule],
      }).compileComponents();
    })
  );

  beforeEach(() => {
    WidgetTypes.splice(0, WidgetTypes.length);
    WidgetTypes.push({
      widgetType: 'TextWidget',
      contentComponentType: <any>TestTextContentComponent,
      widgetUserSettingType: TestTextWidgetUserSetting,
    });

    fixture = TestBed.createComponent(TestWrapperComponent);
    component = fixture.debugElement.children[0].componentInstance;
    dialog = TestBed.inject(AlertService);
    fixture.detectChanges();
  });

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

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

  it('#removeWidget should destroy contentComponent', () => {
    jest.spyOn(dialog, 'openAlertBox');
    jest.spyOn(component.remove, 'emit');

    component.removeWidget();

    expect(dialog.openAlertBox).toHaveBeenCalled();
    expect(component.remove.emit).toHaveBeenCalled();
  });

  it('#editWidget should emit openEdit', () => {
    jest.spyOn(component.openEdit, 'emit');
    component.editWidget();
    expect(component.openEdit.emit).toHaveBeenCalled();
  });

  it('#resize should emit contents resize method', () => {
    jest.spyOn(component.contentComponent.instance, 'resize');
    component.resize();
    expect(component.contentComponent.instance.resize).toHaveBeenCalled();
  });

  it('#resizeWidget should resize widgets according to the size configuration index passed', () => {
    const newSizeArray = [3, 3];
    component.onResizeWidget(newSizeArray);
    expect(component.widget.sizeArray).toEqual(newSizeArray);
  });

  describe('#showBurgerMenu', () => {
    beforeEach(() => {
      component.widget.widgetDefinition.canEdit = false;
      component.widget.widgetDefinition.canRemove = false;
    });

    it('should hide burger menu if no menu options are available', () => {
      expect(component.showBurgerMenu).toBeFalsy();
    });

    it('should show burger menu widget #isEdit is enabled ', () => {
      component.widget.widgetDefinition.canEdit = true;

      expect(component.draggable).toBeTruthy();
    });

    it('should show burger menu if widget #canRemove is enabled ', () => {
      component.widget.widgetDefinition.canRemove = true;

      expect(component.draggable).toBeTruthy();
    });
  });
});
