import { AfterViewInit, Component, OnInit } from '@angular/core';
import { ActivatedRoute, Params, Router } from '@angular/router';
import { AuthProvider } from '@app/core/common/enum/auth-provider';
import { ConfigurableProvider } from '@app/core/model/configurable-provider/configurableProvider';
import { AuthService } from '@app/core/services/auth/auth.service';
import { ConfigurableProvidersService } from '@app/ui/auth/login/utilities/configurableProviders.service';
import { LoginService } from '@app/ui/auth/login/utilities/login.service';
import { BaseComponent } from '@common/base/base.component';
import { environment } from 'environments/environment';
import { takeUntil } from 'rxjs/operators';

/// <reference types="gapi" />
/// <reference types="facebook-js-sdk" />

declare const gapi: any;
declare const FB: any;

@Component({
	selector: 'app-login',
	templateUrl: './login.component.html',
	styleUrls: ['./login.component.scss']
})
export class LoginComponent extends BaseComponent implements OnInit, AfterViewInit {

	public auth2: any;
	private returnUrl: string;
	//public cofigurableProviders: ConfigurableProvider[];

	constructor(
		private router: Router,
		private route: ActivatedRoute,
		private loginService: LoginService,
		private authService: AuthService,
		public configurableProviderService: ConfigurableProvidersService
	) { super(); }

	ngOnInit(): void {
		this.route.queryParams
			.pipe(takeUntil(this._destroyed))
			.subscribe((params: Params) => {
				const returnUrl = params['returnUrl'];
				if (returnUrl) { this.returnUrl = returnUrl; }
			});
		this.authService.getConfigurableProviders()
			.pipe(takeUntil(this._destroyed))
			.subscribe((data: any) => {
				this.configurableProviderService.providers = data;
			})
	}

	ngAfterViewInit() {
		this.initProviders();
	}

	public linkedInLogin() {
		this.router.navigate(['/login/linkedin']);
	}

	public twitterLogin() {
		this.router.navigate(['/login/twitter']);
	}

	public b2AccessLogin() {
		this.router.navigate(['/login/external/b2access']);
	}

	public orcidLogin() {
		this.router.navigate(['/login/external/orcid']);
	}

	public openaireLogin() {
		this.router.navigate(['/login/openaire']);
	}

	public configurableLogin(provider: ConfigurableProvider) {
		this.router.navigate(['/login/configurable/' + provider.configurableLoginId])
	}

	public hasFacebookOauth(): boolean {
		return this.hasProvider(AuthProvider.Facebook);
	}

	public hasLinkedInOauth(): boolean {
		return this.hasProvider(AuthProvider.LinkedIn);
	}

	public hasTwitterOauth(): boolean {
		return this.hasProvider(AuthProvider.Twitter);
	}

	public hasGoogleOauth(): boolean {
		return this.hasProvider(AuthProvider.Google);
	}

	public hasB2AccessOauth(): boolean {
		return this.hasProvider(AuthProvider.B2Access);
	}

	public hasOrcidOauth(): boolean {
		return this.hasProvider(AuthProvider.ORCID);
	}

	public hasOpenAireOauth(): boolean {
		return this.hasProvider(AuthProvider.OpenAire);
	}

	public initProviders() {
		if (this.hasProvider(AuthProvider.Google)) { this.initializeGoogleOauth(); }
		if (this.hasProvider(AuthProvider.Facebook)) { this.initializeFacebookOauth(); }
	}

	public hasProvider(provider: AuthProvider) {
		for (let i = 0; i < environment.loginProviders.enabled.length; i++) {
			if (provider === environment.loginProviders.enabled[i]) { return this.isProviderProperlyConfigured(provider); }
		}
		return false;
	}

	private isProviderProperlyConfigured(provider: AuthProvider) {
		switch (provider) {
			case AuthProvider.Facebook: return this.hasAllRequiredFieldsConfigured(environment.loginProviders.facebookConfiguration);
			case AuthProvider.Google: return this.hasAllRequiredFieldsConfigured(environment.loginProviders.googleConfiguration);
			case AuthProvider.LinkedIn: return this.hasAllRequiredFieldsConfigured(environment.loginProviders.linkedInConfiguration);
			case AuthProvider.Twitter: return this.hasAllRequiredFieldsConfigured(environment.loginProviders.twitterConfiguration);
			case AuthProvider.B2Access: return this.hasAllRequiredFieldsConfigured(environment.loginProviders.b2accessConfiguration);
			case AuthProvider.ORCID: return this.hasAllRequiredFieldsConfigured(environment.loginProviders.orcidConfiguration);
			case AuthProvider.OpenAire: return this.hasAllRequiredFieldsConfigured(environment.loginProviders.openAireConfiguration);
			default: throw new Error('Unsupported Provider Type');
		}
	}

	private hasAllRequiredFieldsConfigured(configuration: any) {
		if (configuration != null && configuration.clientId != null) { return true; }
		return false;
	}

	/*
	* GOOGLE SIGN IN
	*/
	private initializeGoogleOauth(): void {
		gapi.load('auth2', () => {
			this.auth2 = gapi.auth2.init({
				client_id: environment.loginProviders.googleConfiguration.clientId,
				scope: 'profile email'
			});
			this.attachGoogleSignΙn(document.getElementById('googleSignInButton'));
		});
	}

	public attachGoogleSignΙn(element) {
		if (!element) { return; }
		this.auth2.attachClickHandler(element, {},
			(googleUser) => {
				const id_token = googleUser.getAuthResponse().id_token;
				if (id_token) {
					this.authService.login({ ticket: id_token, provider: AuthProvider.Google })
						.pipe(takeUntil(this._destroyed))
						.subscribe(
							res => this.loginService.onLogInSuccess(res, this.returnUrl),
							error => this.loginService.onLogInError(error)
						);
				}
			}, (error) => {
			});
	}

	/*
	* FACEBOOK SIGN IN
	*/
	private initializeFacebookOauth(): void {
		FB.init({
			appId: environment.loginProviders.facebookConfiguration.clientId,
			cookie: false,
			xfbml: true,
			version: 'v2.8'
		});
	}

	public facebookLogin() {
		FB.login((response: any) => {
			if (response.status === 'connected' || 'not_authorized') {
				this.authService.login({ ticket: response.authResponse.accessToken, provider: AuthProvider.Facebook })
					.pipe(takeUntil(this._destroyed))
					.subscribe(
						res => this.loginService.onLogInSuccess(res, this.returnUrl),
						error => this.loginService.onLogInError(error)
					);
			}
		}, { scope: 'user_friends,email' });
	}

	public hasConfigurableProviders(): boolean {
		return !(this.configurableProviderService.providers == undefined) && this.configurableProviderService.providers.length > 0
	}
}
