
import { AfterViewInit, Component } from '@angular/core';
import { FormArray, FormGroup } from '@angular/forms';
import { ActivatedRoute, Params, Router } from '@angular/router';
import { DmpProfileFieldDataType } from '@app/core/common/enum/dmp-profile-field-type';
import { DmpProfileStatus } from '@app/core/common/enum/dmp-profile-status';
import { DmpProfileType } from '@app/core/common/enum/dmp-profile-type';
import { DmpProfile } from '@app/core/model/dmp-profile/dmp-profile';
import { DmpProfileService } from '@app/core/services/dmp/dmp-profile.service';
import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service';
import { EnumUtils } from '@app/core/services/utilities/enum-utils.service';
import { DmpProfileEditorModel, DmpProfileFieldEditorModel } from '@app/ui/admin/dmp-profile/editor/dmp-profile-editor.model';
import { DmpProfileExternalAutoCompleteFieldDataEditorModel } from '@app/ui/admin/dmp-profile/editor/external-autocomplete/dmp-profile-external-autocomplete-field-editor.model';
import { BreadcrumbItem } from '@app/ui/misc/breadcrumb/definition/breadcrumb-item';
import { BaseComponent } from '@common/base/base.component';
import { FormService } from '@common/forms/form-service';
import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model';
import { TranslateService } from '@ngx-translate/core';
import { environment } from 'environments/environment';
import * as FileSaver from 'file-saver';
import { Observable, of as observableOf } from 'rxjs';
import { map, takeUntil } from 'rxjs/operators';
import { ConfigurationService } from '@app/core/services/configuration/configuration.service';
import { HttpClient } from '@angular/common/http';
import { MatomoService } from '@app/core/services/matomo/matomo-service';
import { MatDialog } from '@angular/material/dialog';
import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component';


@Component({
	selector: 'app-dmp-profile-editor-component',
	templateUrl: 'dmp-profile-editor.component.html',
	styleUrls: ['./dmp-profile-editor.component.scss']
})
export class DmpProfileEditorComponent extends BaseComponent implements AfterViewInit {

	isNew = true;
	viewOnly = false;
	dmpProfileModel: DmpProfileEditorModel;
	formGroup: FormGroup = null;
	host: string;
	dmpProfileId: string;
	breadCrumbs: Observable<BreadcrumbItem[]>;

	constructor(
		private dmpProfileService: DmpProfileService,
		private route: ActivatedRoute,
		private router: Router,
		private language: TranslateService,
		private enumUtils: EnumUtils,
		private uiNotificationService: UiNotificationService,
		private formService: FormService,
		private configurationService: ConfigurationService,
		private httpClient: HttpClient,
		private matomoService: MatomoService,
		private dialog: MatDialog
	) {
		super();
		this.host = configurationService.server;
	}

	ngAfterViewInit() {
		this.matomoService.trackPageView('Admin: DMP Profile Edit');
		this.route.params
			.pipe(takeUntil(this._destroyed))
			.subscribe((params: Params) => {
				this.dmpProfileId = params['id'];

				if (this.dmpProfileId != null) {
					this.isNew = false;
					this.dmpProfileService.getSingle(this.dmpProfileId).pipe(map(data => data as DmpProfile))
						.pipe(takeUntil(this._destroyed))
						.subscribe(data => {
							this.dmpProfileModel = new DmpProfileEditorModel().fromModel(data);
							this.formGroup = this.dmpProfileModel.buildForm();
							if (this.dmpProfileModel.status == DmpProfileStatus.Finalized) {
								this.formGroup.disable();
								this.viewOnly = true
							}
							this.breadCrumbs = observableOf([{
								parentComponentName: 'DmpProfileListingComponent',
								label: this.language.instant('NAV-BAR.TEMPLATE'),
								url: '/dmp-profiles/' + this.dmpProfileId
							}]);
						});
				} else {
					this.dmpProfileModel = new DmpProfileEditorModel();
					setTimeout(() => {
						this.formGroup = this.dmpProfileModel.buildForm();
						this.addField();
					});
					this.breadCrumbs = observableOf([{
						parentComponentName: 'DmpProfileListingComponent',
						label: this.language.instant('NAV-BAR.TEMPLATE'),
						url: '/dmp-profiles/' + this.dmpProfileId
					}]);
				}
			});
	}

	formSubmit(): void {
		this.formService.touchAllFormFields(this.formGroup);
		if (!this.isFormValid()) { return; }
		this.onSubmit();
	}

	public isFormValid() {
		return this.formGroup.valid;
	}

	onSubmit(): void {
		this.dmpProfileService.createDmp(this.formGroup.value)
			.pipe(takeUntil(this._destroyed))
			.subscribe(
				complete => this.onCallbackSuccess(),
				error => this.onCallbackError(error)
			);
	}

	onCallbackSuccess(): void {
		this.uiNotificationService.snackBarNotification(this.isNew ? this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-CREATION') : this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE'), SnackBarNotificationLevel.Success);
		this.router.navigate(['/dmp-profiles']);
	}

	onCallbackError(errorResponse: any) {
		this.setErrorModel(errorResponse.error);
		this.formService.validateAllFormFields(this.formGroup);
	}

	public setErrorModel(validationErrorModel: ValidationErrorModel) {
		Object.keys(validationErrorModel).forEach(item => {
			(<any>this.dmpProfileModel.validationErrorModel)[item] = (<any>validationErrorModel)[item];
		});
	}

	public cancel(): void {
		this.router.navigate(['/dmp-profiles']);
	}

	addField() {
		(<FormArray>this.formGroup.get('definition').get('fields')).push(new DmpProfileFieldEditorModel().buildForm());
	}

	removeField(index: number) {
		(<FormArray>this.formGroup.get('definition').get('fields')).controls.splice(index, 1);
	}

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

	getDMPProfileFieldDataTypeWithLanguage(fieldType: DmpProfileFieldDataType): string {
		let result = '';
		this.language.get(this.enumUtils.toDmpProfileFieldDataTypeString(fieldType))
			.pipe(takeUntil(this._destroyed))
			.subscribe((value: string) => {
				result = value;
			});
		return result;
	}

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

	getDMPProfileFieldTypeWithLanguage(profileType: DmpProfileType): string {
		let result = '';
		this.language.get(this.enumUtils.toDmpProfileTypeString(profileType))
			.pipe(takeUntil(this._destroyed))
			.subscribe((value: string) => {
				result = value;
			});
		return result;
	}

	delete() {
		this.dialog.open(ConfirmationDialogComponent,{data:{
			isDeleteConfirmation: true,
			confirmButton: this.language.instant('DMP-PROFILE-EDITOR.CONFIRM-DELETE-DIALOG.CONFIRM-BUTTON'),
			cancelButton: this.language.instant("DMP-PROFILE-EDITOR.CONFIRM-DELETE-DIALOG.CANCEL-BUTTON"),
			message: this.language.instant("DMP-PROFILE-EDITOR.CONFIRM-DELETE-DIALOG.MESSAGE")
		}})
		.afterClosed()
		.subscribe(
			confirmed =>{
				if(confirmed){
					this.formGroup.get('status').setValue(DmpProfileStatus.Deleted);
					this.dmpProfileService.createDmp(this.formGroup.value)
						.pipe(takeUntil(this._destroyed))
						.subscribe(
							complete => this.onCallbackSuccess(),
							error => this.onCallbackError(error)
					);
				}
			}
		)

	}

	finalize() {
		//const data = this.form.value;
		this.formGroup.get('status').setValue(DmpProfileStatus.Finalized);

		this.onSubmit();
	}

	downloadXML(): void {
		this.dmpProfileService.downloadXML(this.dmpProfileId)
			.pipe(takeUntil(this._destroyed))
			.subscribe(response => {
				const blob = new Blob([response.body], { type: 'application/xml' });
				const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));

				FileSaver.saveAs(blob, filename);
			});
	}


	getFilenameFromContentDispositionHeader(header: string): string {
		const regex: RegExp = new RegExp(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/g);

		const matches = header.match(regex);
		let filename: string;
		for (let i = 0; i < matches.length; i++) {
			const match = matches[i];
			if (match.includes('filename="')) {
				filename = match.substring(10, match.length - 1);
				break;
			} else if (match.includes('filename=')) {
				filename = match.substring(9);
				break;
			}
		}
		return filename;
	}

	isExternalAutocomplete(formGroup: FormGroup) {
		if (formGroup.get('dataType').value == DmpProfileFieldDataType.ExternalAutocomplete) {
			this.addControl(formGroup);
			return true;
		} else {
			return false;
		}
	}

	addControl(formGroup: FormGroup) {
		if (formGroup.get('dataType').value == 3)
			formGroup.addControl('externalAutocomplete', new DmpProfileExternalAutoCompleteFieldDataEditorModel().buildForm());
	}
}
