import { Component, Input, OnInit } from '@angular/core';
import { AbstractControl, FormArray, FormBuilder, FormControl, FormGroup } from '@angular/forms';
import { AppRole } from '@app/core/common/enum/app-role';
import { UserListingModel } from '@app/core/model/user/user-listing';
import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service';
import { UserService } from '@app/core/services/user/user.service';
import { EnumUtils } from '@app/core/services/utilities/enum-utils.service';
import { BaseComponent } from '@common/base/base.component';
import { Validation, ValidationContext } from '@common/forms/validation/validation-context';
import { TranslateService } from '@ngx-translate/core';
import { takeUntil } from 'rxjs/operators';

@Component({
	selector: 'app-user-role-editor-component',
	templateUrl: './user-role-editor.component.html',
	styleUrls: ['./user-role-editor.component.scss']
})
export class UserRoleEditorComponent extends BaseComponent implements OnInit {

	@Input() public item: UserListingModel;
	public formGroup: FormGroup = null;
	public nowEditing = false;

	constructor(
		private language: TranslateService,
		private userService: UserService,
		private formBuilder: FormBuilder,
		private enumUtils: EnumUtils,
		private uiNotificationService: UiNotificationService
	) { super(); }

	ngOnInit() {
		if (this.formGroup == null) { this.formGroup = this.buildForm(); }
	}

	buildForm(): FormGroup {
		const context: ValidationContext = this.createValidationContext();

		return this.formBuilder.group({
			appRoles: new FormControl({ value: this.item.appRoles, disabled: true }, context.getValidation('appRoles').validators)
		});
	}

	createValidationContext(): ValidationContext {
		const validationContext: ValidationContext = new ValidationContext();
		const validationArray: Validation[] = new Array<Validation>();

		validationArray.push({ key: 'appRoles' });

		validationContext.validation = validationArray;
		return validationContext;
	}

	formSubmit(): void {

		const modifiedItem = this.item;
		modifiedItem.appRoles = this.getFormControl('appRoles').value;

		if (!this.isFormValid()) { return; }
		this.userService.updateRoles(modifiedItem)
			.pipe(takeUntil(this._destroyed))
			.subscribe(
				(res) => this.onCallbackSuccess(),
				(error) => this.onCallbackError(error)
			);
	}

	editItem(): void {
		this.formGroup.enable();
		this.nowEditing = true;
	}

	isFormValid(): boolean {
		this.touchAllFormFields(this.formGroup);
		this.validateAllFormFields(this.formGroup);
		return this.formGroup.valid;
	}

	getFormData(): any {
		return this.formGroup.value;
	}

	getFormControl(controlName: string): AbstractControl {
		return this.formGroup.get(controlName);
	}

	validateAllFormFields(formControl: AbstractControl) {
		if (formControl instanceof FormControl) {
			formControl.updateValueAndValidity({ emitEvent: false });
		} else if (formControl instanceof FormGroup) {
			Object.keys(formControl.controls).forEach(item => {
				const control = formControl.get(item);
				this.validateAllFormFields(control);
			});
		} else if (formControl instanceof FormArray) {
			formControl.controls.forEach(item => {
				this.validateAllFormFields(item);
			});
		}
	}

	touchAllFormFields(formControl: AbstractControl) {
		if (formControl instanceof FormControl) {
			formControl.markAsTouched();
		} else if (formControl instanceof FormGroup) {
			Object.keys(formControl.controls).forEach(item => {
				const control = formControl.get(item);
				this.touchAllFormFields(control);
			});
		} else if (formControl instanceof FormArray) {
			formControl.controls.forEach(item => {
				this.touchAllFormFields(item);
			});
		}
	}

	onCallbackSuccess() {
		this.nowEditing = false;
		this.formGroup.disable();
		this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE'), SnackBarNotificationLevel.Success);
	}

	onCallbackError(error: any) {
		this.validateAllFormFields(this.formGroup);
		this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-UPDATE'), SnackBarNotificationLevel.Error);
	}

	getPrincipalAppRoleValues(): Number[] {
		let keys: string[] = Object.keys(AppRole);
		keys = keys.slice(0, keys.length / 2);
		const values: Number[] = keys.map(Number);
		return values;
	}

	getPrincipalAppRoleWithLanguage(role: AppRole): string {
		let result = '';
		this.language.get(this.enumUtils.convertFromPrincipalAppRole(role))
			.pipe(takeUntil(this._destroyed))
			.subscribe((value: string) => {
				result = value;
			});
		return result;
	}
}
