import {async, ComponentFixture, fakeAsync, TestBed, tick} from '@angular/core/testing';
import { LoginComponent } from './login.component';
import {LoginService} from '../services/login.service';
import {ValidationService} from '../services/validation.service';
import {FormsModule} from '@angular/forms';
import {By} from '@angular/platform-browser';
import {ValidateDirective} from '../validate.directive';
import {RbUiComponentsModule} from '@inst-iot/bosch-angular-ui-components';
import {ApiService} from '../services/api.service';
import {RouterTestingModule} from '@angular/router/testing';
import {Router} from '@angular/router';

// TODO

let validationServiceSpy: jasmine.SpyObj<ValidationService>;
let loginServiceSpy: jasmine.SpyObj<LoginService>;
let apiServiceSpy: jasmine.SpyObj<ApiService>;
let routerServiceSpy: Router;

describe('LoginComponent', () => {
  let component: LoginComponent;
  let fixture: ComponentFixture<LoginComponent>;
  let css;   // get native element by css selector
  let cssd;  // get debug element by css selector

  beforeEach(async(() => {
    const validationSpy = jasmine.createSpyObj('ValidationService', ['username', 'password']);
    const loginSpy = jasmine.createSpyObj('LoginService', ['login']);
    const apiSpy = jasmine.createSpyObj('ApiService', ['post', 'put']);

    TestBed.configureTestingModule({
      declarations: [ LoginComponent, ValidateDirective ],
      imports: [
        RbUiComponentsModule,
        FormsModule,
        RouterTestingModule
      ],
      providers: [
        {provide: ValidationService, useValue: validationSpy},
        {provide: LoginService, useValue: loginSpy},
        {provide: ApiService, useValue: apiSpy}
      ]
    })
    .compileComponents();

    validationServiceSpy = TestBed.inject(ValidationService) as jasmine.SpyObj<ValidationService>;
    loginServiceSpy = TestBed.inject(LoginService) as jasmine.SpyObj<LoginService>;
    apiServiceSpy = TestBed.inject(ApiService) as jasmine.SpyObj<ApiService>;
    routerServiceSpy = TestBed.inject(Router);
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(LoginComponent);
    component = fixture.componentInstance;
    component.ngOnInit();
    fixture.detectChanges();
    cssd = (selector) => fixture.debugElement.query(By.css(selector));
    css = (selector) => fixture.debugElement.query(By.css(selector)).nativeElement;
  });

  it('should create', () => {
    validationServiceSpy.username.and.returnValue({ok: true, error: ''});
    validationServiceSpy.password.and.returnValue({ok: true, error: ''});
    expect(component).toBeTruthy();
  });

  // it('should have the `Please log in` heading', () => {
  //   expect(css('h2').innerText).toBe('Please log in');
  // });
  //
  // it('should have empty credential inputs', () => {
  //   expect(css('rb-form-input[label=username] input').value).toBe('');
  //   expect(css('rb-form-input[label=password] input').value).toBe('');
  // });
  //
  // it('should have an empty message at the beginning', () => {
  //   expect(css('.message').innerText).toBe('');
  // });
  //
  // it('should have a login button', async () => {
  //   validationServiceSpy.username.and.returnValue({ok: true, error: ''});
  //   validationServiceSpy.password.and.returnValue({ok: true, error: ''});
  //   await fixture.whenStable();
  //   fixture.detectChanges();
  //   expect(css('.login-button')).toBeTruthy();
  //   expect(css('.login-button').disabled).toBeTruthy();
  // });
  //
  // it('should reject a wrong username', async () => {
  //   validationServiceSpy.username.and.returnValue({ok: false, error: 'username must only contain a-z0-9-_.'});
  //   component.username = 'ab#';
  //   fixture.detectChanges();
  //   await fixture.whenRenderingDone();
  //   expect(component.loginForm.controls.username.valid).toBeFalsy();
  //   expect(validationServiceSpy.username).toHaveBeenCalledWith('ab#');
  // });
  //
  // it('should reject a wrong password', async () => {
  //   validationServiceSpy.password.and.returnValue({ok: false, error: 'password must only contain a-zA-Z0-9!"#%&\'()*+,-./:;<=>?@[]^_`{|}~'});
  //   component.password = 'abc';
  //
  //   fixture.detectChanges();
  //   await fixture.whenRenderingDone();
  //   expect(component.loginForm.controls.password.valid).toBeFalsy();
  //   expect(validationServiceSpy.password).toHaveBeenCalledWith('abc');
  // });
  //
  // it('should enable the login button with valid credentials', async () => {
  //   validationServiceSpy.username.and.returnValue({ok: true, error: ''});
  //   validationServiceSpy.password.and.returnValue({ok: true, error: ''});
  //   loginServiceSpy.login.and.returnValue(new Promise(r => r(true)));
  //
  //   fixture.detectChanges();
  //   await fixture.whenRenderingDone();
  //
  //   cssd('.login-button').triggerEventHandler('click', null);
  //   expect(css('.login-button').disabled).toBeFalsy();
  //   expect(loginServiceSpy.login.calls.count()).toBe(1);
  // });
  //
  // it('should call the LoginService with valid credentials', () => {
  //   validationServiceSpy.username.and.returnValue({ok: true, error: ''});
  //   validationServiceSpy.password.and.returnValue({ok: true, error: ''});
  //   loginServiceSpy.login.and.returnValue(new Promise(r => r(true)));
  //
  //   cssd('.login-button').triggerEventHandler('click', null);
  //   expect(loginServiceSpy.login.calls.count()).toBe(1);
  // });
  //
  // it('should display an error if the LoginService could not authenticate', fakeAsync(() => {
  //   validationServiceSpy.username.and.returnValue({ok: true, error: ''});
  //   validationServiceSpy.password.and.returnValue({ok: true, error: ''});
  //   loginServiceSpy.login.and.returnValue(new Promise(r => r(false)));
  //
  //   cssd('.login-button').triggerEventHandler('click', null);
  //   expect(loginServiceSpy.login.calls.count()).toBe(1);
  //   tick();
  //   fixture.detectChanges();
  //   expect(css('.message').innerText).toBe('Wrong credentials!');
  // }));
});
