
import { Component, OnInit } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { MatDialog } from '@angular/material/dialog';
import { ActivatedRoute, Params, Router } from '@angular/router';
import { DmpStatus } from '@app/core/common/enum/dmp-status';
import { DataTableRequest } from '@app/core/model/data-table/data-table-request';
import { DmpProfileDefinition } from '@app/core/model/dmp-profile/dmp-profile';
import { DmpProfileListing } from '@app/core/model/dmp-profile/dmp-profile-listing';
import { DmpModel } from '@app/core/model/dmp/dmp';
import { UserModel } from '@app/core/model/user/user';
import { UserInfoListingModel } from '@app/core/model/user/user-info-listing';
import { BaseCriteria } from '@app/core/query/base-criteria';
import { DmpProfileCriteria } from '@app/core/query/dmp/dmp-profile-criteria';
import { GrantCriteria } from '@app/core/query/grant/grant-criteria';
import { RequestItem } from '@app/core/query/request-item';
import { AuthService } from '@app/core/services/auth/auth.service';
import { DmpProfileService } from '@app/core/services/dmp/dmp-profile.service';
import { DmpService } from '@app/core/services/dmp/dmp.service';
import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service';
import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component';
import { DmpEditorModel } from '@app/ui/dmp/editor/dmp-editor.model';
import { DmpFinalizeDialogComponent, DmpFinalizeDialogInput } from '@app/ui/dmp/editor/dmp-finalize-dialog/dmp-finalize-dialog.component';
import { FunderFormModel } from '@app/ui/dmp/editor/grant-tab/funder-form-model';
import { GrantTabModel } from '@app/ui/dmp/editor/grant-tab/grant-tab-model';
import { ProjectFormModel } from '@app/ui/dmp/editor/grant-tab/project-form-model';
import { BreadcrumbItem } from '@app/ui/misc/breadcrumb/definition/breadcrumb-item';
import { IBreadCrumbComponent } from '@app/ui/misc/breadcrumb/definition/IBreadCrumbComponent';
import { BaseComponent } from '@common/base/base.component';
import { FormService } from '@common/forms/form-service';
import { FormValidationErrorsDialogComponent } from '@common/forms/form-validation-errors-dialog/form-validation-errors-dialog.component';
import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model';
import { TranslateService } from '@ngx-translate/core';
import * as FileSaver from 'file-saver';
import { Observable, of as observableOf } from 'rxjs';
import { map, takeUntil } from 'rxjs/operators';
import { Principal } from "@app/core/model/auth/Principal";
import { Role } from "@app/core/common/enum/role";

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

	editMode = true;
	// editMode = false;

	breadCrumbs: Observable<BreadcrumbItem[]>;
	isNew = true;
	isPublic = false;
	isFinalized = false;
	dmp: DmpEditorModel;
	formGroup: FormGroup = null;
	selectedTab = 0;

	createNewVersion;
	associatedUsers: Array<UserModel>;
	people: Array<UserInfoListingModel>;
	filteredOptions: DmpProfileListing[];
	selectedDmpProfileDefinition: DmpProfileDefinition;
	DynamicDmpFieldResolverComponent: any;
	isUserOwner: boolean = true;

	constructor(
		private dmpProfileService: DmpProfileService,
		private dmpService: DmpService,
		private route: ActivatedRoute,
		private router: Router,
		private language: TranslateService,
		private dialog: MatDialog,
		private uiNotificationService: UiNotificationService,
		private authentication: AuthService,
		private authService: AuthService,
		private formService: FormService
	) {
		super();
	}

	ngOnInit() {
		this.route.params
			.pipe(takeUntil(this._destroyed))
			.subscribe((params: Params) => {
				const itemId = params['id'];
				const publicId = params['publicId'];
				const queryParams = this.route.snapshot.queryParams;
				const tabToNav = queryParams['tab'];

				const grantRequestItem: RequestItem<GrantCriteria> = new RequestItem();
				grantRequestItem.criteria = new GrantCriteria();
				const organisationRequestItem: RequestItem<BaseCriteria> = new RequestItem();
				organisationRequestItem.criteria = new BaseCriteria();

				// this.grantAutoCompleteConfiguration = {
				// 	filterFn: this.searchGrant.bind(this),
				// 	initialItems: (extraData) => this.searchGrant(''),
				// 	displayFn: (item) => item['label'],
				// 	titleFn: (item) => item['label']
				// };
				if (itemId != null) {
					this.isNew = false;
					if (tabToNav == "datasetDescriptions") this.selectedTab = 2
					this.dmpService.getSingle(itemId).pipe(map(data => data as DmpModel))
						.pipe(takeUntil(this._destroyed))
						.subscribe(async data => {
							this.dmp = new DmpEditorModel();
							this.dmp.grant = new GrantTabModel();
							this.dmp.project = new ProjectFormModel();
							this.dmp.funder = new FunderFormModel();
							this.dmp.fromModel(data);
							this.formGroup = this.dmp.buildForm();
							this.setIsUserOwner();
							if (!this.isUserOwner) {
								this.isFinalized = true;
								this.formGroup.disable();
							}
							//this.registerFormEventsForDmpProfile(this.dmp.definition);
							if (!this.editMode || this.dmp.status === DmpStatus.Finalized) {
								this.isFinalized = true;
								this.formGroup.disable();
							}
							if (this.isAuthenticated) {
								// if (!this.isAuthenticated) {
								const breadCrumbs = [];
								breadCrumbs.push({
									parentComponentName: null,
									label: this.language.instant('NAV-BAR.MY-DMPS'),
									url: "/plans"
								});
								breadCrumbs.push({
									parentComponentName: 'DmpListingComponent',
									label: this.dmp.label,
									url: '/plans/edit/' + this.dmp.id,
									// notFoundResolver: [await this.grantService.getSingle(this.dmp.grant.id).map(x => ({ label: x.label, url: '/grants/edit/' + x.id }) as BreadcrumbItem).toPromise()]
								}
								);
								this.breadCrumbs = observableOf(breadCrumbs);
							}
							this.associatedUsers = data.associatedUsers;
							this.people = data.users;
						});
				} else if (publicId != null) {
					this.isNew = false;
					this.isPublic = true;
					this.dmpService.getSinglePublic(publicId).pipe(map(data => data as DmpModel))
						.pipe(takeUntil(this._destroyed))
						.subscribe(async data => {
							this.dmp = new DmpEditorModel();
							this.dmp.grant = new GrantTabModel();
							this.dmp.project = new ProjectFormModel();
							this.dmp.funder = new FunderFormModel();
							this.dmp.fromModel(data);
							this.formGroup = this.dmp.buildForm();
							//this.registerFormEventsForDmpProfile(this.dmp.definition);
							if (!this.editMode || this.dmp.status === DmpStatus.Finalized) { this.formGroup.disable(); }
							// if (!this.isAuthenticated) {
							const breadcrumbs = [];
							breadcrumbs.push({ parentComponentName: null, label: this.language.instant('NAV-BAR.PUBLIC-DMPS').toUpperCase(), url: '/plans' });
							breadcrumbs.push({ parentComponentName: null, label: this.dmp.label, url: '/plans/publicEdit/' + this.dmp.id });
							this.breadCrumbs = observableOf(breadcrumbs);
							// this.breadCrumbs = Observable.of([
							// 	{
							// 		parentComponentName: 'DmpListingComponent',
							// 		label: this.language.instant('NAV-BAR.MY-DMPS'),
							// 		url: 'plans',
							// 		notFoundResolver: [await this.grantService.getSingle(this.dmp.grant.id).map(x => ({ label: x.label, url: '/grants/edit/' + x.id }) as BreadcrumbItem).toPromise()]
							// 	}]
							// );
							this.associatedUsers = data.associatedUsers;
							// }
						});
				} else {
					this.dmp = new DmpEditorModel();
					this.dmp.grant = new GrantTabModel();
					this.dmp.project = new ProjectFormModel();
					this.dmp.funder = new FunderFormModel();
					this.formGroup = this.dmp.buildForm();
					this.registerFormEventsForNewItem();
					if (this.isAuthenticated) {
						this.language.get('NAV-BAR.MY-DMPS').pipe(takeUntil(this._destroyed)).subscribe(x => {
							this.breadCrumbs = observableOf([
								{
									parentComponentName: null,
									label: x,
									url: '/plans'
								},
								{
									parentComponentName: null,
									label: "CREATE NEW DMP",
									url: "/plans/new"
								}
							]);
						})
					}
				}
			});

		this.route
			.queryParams
			.pipe(takeUntil(this._destroyed))
			.subscribe(params => {
				this.createNewVersion = params['clone'];
			});
	}

	isAuthenticated() {
		return this.authService.current() != null;
	}

	setIsUserOwner() {
		if (this.dmp) {
			const principal: Principal = this.authentication.current();
			this.isUserOwner = principal.id === this.dmp.users.find(x => x.role === Role.Owner).id;
		}
	}

	registerFormEventsForNewItem() {
		this.breadCrumbs = observableOf([
			{
				parentComponentName: 'DmpListingComponent',
				label: this.language.instant('NAV-BAR.MY-DMPS'),
				url: 'plans',
			}
		]);
	}

	dmpProfileSearch(query: string) {
		let fields: Array<string> = new Array();
		var request = new DataTableRequest<DmpProfileCriteria>(0, 10, { fields: fields });
		request.criteria = new DmpProfileCriteria();
		return this.dmpProfileService.getPaged(request).pipe(map(x => x.data));
	}

	// searchGrant(query: string) {
	// 	const grantRequestItem: RequestItem<GrantCriteria> = new RequestItem();
	// 	grantRequestItem.criteria = new GrantCriteria();
	// 	grantRequestItem.criteria.like = query;
	// 	return this.grantService.getWithExternal(grantRequestItem);
	// }

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

	public isFormValid() {
		return this.formGroup.valid;
		// return this.formGroup.get('label').valid && this.formGroup.get('profiles').valid &&
		// 	(this.formGroup.get('funder').get('label').valid || this.formGroup.get('funder').get('existFunder').valid) &&
		// 	(this.formGroup.get('grant').get('label').valid || this.formGroup.get('grant').get('existGrant').valid);
	}

	private showValidationErrorsDialog(projectOnly?: boolean) {
		const dialogRef = this.dialog.open(FormValidationErrorsDialogComponent, {
			disableClose: true,
			data: {
				formGroup: this.formGroup,
				projectOnly: projectOnly
			},
		});
	}

	onSubmit(showAddDatasetDialog?: boolean): void {
		this.dmpService.createDmp(this.formGroup.getRawValue())
			.pipe(takeUntil(this._destroyed))
			.subscribe(
				complete => {
					if (showAddDatasetDialog) {
						this.addDatasetOpenDialog(complete);
					}
					else { this.onCallbackSuccess(complete) }
				},
				error => {
					this.formGroup.get('status').setValue(DmpStatus.Draft);
					this.onCallbackError(error);
				}
			);

	}

	onCallbackSuccess(id?: String): void {
		this.uiNotificationService.snackBarNotification(this.isNew ? this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-CREATION') : this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE'), SnackBarNotificationLevel.Success);
		id != null ? this.router.navigate(['/reload']).then(() => { this.router.navigate(['/plans', 'edit', id]); }) : this.router.navigate(['/reload']).then(() => { this.router.navigate(['/plans']); });
	}

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

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

	public cancel(id: String): void {
		if (id != null) {
			this.router.navigate(['/plans/overview/' + id]);
		} else {
			this.router.navigate(['/plans']);
		}
	}

	public invite(): void {
		this.router.navigate(['/invite/' + this.dmp.id]);
	}

	public delete(): void {
		const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
			maxWidth: '300px',
			restoreFocus: false,
			data: {
				message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.DELETE-ITEM'),
				confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.DELETE'),
				cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL'),
				isDeleteConfirmation: true
			}
		});
		dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
			if (result) {
				this.dmpService.delete(this.dmp.id)
					.pipe(takeUntil(this._destroyed))
					.subscribe(
						complete => { this.onCallbackSuccess() },
						error => this.onDeleteCallbackError(error)
					);
			}
		});
	}
	onDeleteCallbackError(error) {
		this.uiNotificationService.snackBarNotification(error.error.message ? error.error.message : this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-DELETE'), SnackBarNotificationLevel.Error);
	}

	displayWith(item: any) {
		if (!item) { return null; }
		return item['label'];
	}

	redirectToGrant() {
		this.router.navigate(['grants/edit/' + this.dmp.grant.id]);
	}

	redirectToDatasets() {
		this.router.navigate(['datasets'], { queryParams: { dmpId: this.dmp.id } });
	}

	newVersion(id: String, label: String) {
		this.router.navigate(['/plans/new_version/' + id, { dmpLabel: label }]);
	}

	clone(id: String) {
		this.router.navigate(['/plans/clone/' + id]);
	}

	viewVersions(rowId: String, rowLabel: String) {
		this.router.navigate(['/plans/versions/' + rowId], { queryParams: { groupLabel: rowLabel } });
	}

	downloadXml(id: string) {
		this.dmpService.downloadXML(id)
			.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);
			});
	}

	downloadDocx(id: string) {
		this.dmpService.downloadDocx(id)
			.pipe(takeUntil(this._destroyed))
			.subscribe(response => {
				const blob = new Blob([response.body], { type: 'application/msword' });
				const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
				FileSaver.saveAs(blob, filename);
			});
	}

	downloadPDF(id: string) {
		this.dmpService.downloadPDF(id)
			.pipe(takeUntil(this._destroyed))
			.subscribe(response => {
				const blob = new Blob([response.body], { type: 'application/pdf' });
				const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
				FileSaver.saveAs(blob, filename);
			});
	}

	downloadJson(id: string) {
		this.dmpService.downloadJson(id)
			.pipe(takeUntil(this._destroyed))
			.subscribe(response => {
				const blob = new Blob([response.body], { type: 'application/json' });
				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;
	}

	public enableForm() {
		if (this.formGroup.get('status').value !== DmpStatus.Finalized) {
			this.editMode = true;
			this.formGroup.enable();
		}
		//else {
		// 	this.dmpService.unlock(this.formGroup.get('id').value)
		// 		.pipe(takeUntil(this._destroyed))
		// 		.subscribe(x => {
		// 			this.editMode = true;
		// 			this.formGroup.get('status').patchValue(DmpStatus.Draft);
		// 			this.formGroup.enable();
		// 		});
		// }
	}

	public disableForm() {
		this.editMode = false;
		this.formGroup.disable();
	}

	addDataset() {
		this.formSubmit(true);
	}

	addDatasetOpenDialog(id: String) {
		const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
			maxWidth: '500px',
			restoreFocus: false,
			data: {
				message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ADD-DATASET'),
				confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CONFIRM'),
				cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.NO'),
				isDeleteConfirmation: false
			}
		});

		dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
			if (result) {
				this.router.navigate(['datasets/new/' + id]);
			} else {
				id != null ? this.router.navigate(['/plans', 'edit', id]) : this.router.navigate(['/plans']);
			}
		});
	}

	saveAndFinalize() {
		const dialogInputModel: DmpFinalizeDialogInput = {
			dmpLabel: this.formGroup.get('label').value,
			dmpDescription: this.formGroup.get('description').value,
			datasets: this.formGroup.get('datasets').value.map(x => {
				return { label: x.label, id: x.id, status: x.status };
			})
		}

		const dialogRef = this.dialog.open(DmpFinalizeDialogComponent, {
			maxWidth: '500px',
			restoreFocus: false,
			data: {
				dialogInputModel: dialogInputModel,
				message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.FINALIZE-ITEM'),
				confirmButton: this.language.instant('DMP-FINALISE-DIALOG.SUBMIT'),
				cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL'),
			}
		});
		dialogRef.afterClosed()
			.pipe(takeUntil(this._destroyed))
			.subscribe(result => {
				if (result && !result.cancelled) {
					this.formGroup.get('status').setValue(DmpStatus.Finalized);
					this.formGroup.get('datasetsToBeFinalized').setValue(result.datasetsToBeFinalized);
					this.formSubmit(false);
					//this.router.navigate(['/plans/overview/' + this.formGroup.get('id').value]);
					dialogRef.close();
				}
			});
	}

	// advancedClicked() {
	// 	const dialogRef = this.dialog.open(ExportMethodDialogComponent, {
	// 		maxWidth: '500px',
	// 		data: {
	// 			message: "Download as:",
	// 			XMLButton: "XML",
	// 			documentButton: "Document",
	// 			pdfButton: "PDF",
	// 			jsonButton: "JSON"
	// 		}
	// 	});
	// 	dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
	// 		if (result == "pdf") {
	// 			this.downloadPDF(this.dmp.id);
	// 		} else if (result == "xml") {
	// 			this.downloadXml(this.dmp.id);
	// 		} else if (result == "doc") {
	// 			this.downloadDocx(this.dmp.id);
	// 		} else if (result == "json") {
	// 			this.downloadJson(this.dmp.id)
	// 		}
	// 	});
	// }
}
