
import { Component, OnInit } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { ActivatedRoute, Params, Router } from '@angular/router';
import { DatasetStatus } from '@app/core/common/enum/dataset-status';
import { DmpStatus } from '@app/core/common/enum/dmp-status';
import { Principal } from '@app/core/model/auth/Principal';
import { DatasetOverviewModel } from '@app/core/model/dataset/dataset-overview';
import { DatasetsToBeFinalized } from '@app/core/model/dataset/datasets-toBeFinalized';
import { DmpOverviewModel } from '@app/core/model/dmp/dmp-overview';
import { UserInfoListingModel } from '@app/core/model/user/user-info-listing';
import { AuthService } from '@app/core/services/auth/auth.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 { DmpFinalizeDialogComponent, DmpFinalizeDialogInput, DmpFinalizeDialogOutput } from '@app/ui/dmp/editor/dmp-finalize-dialog/dmp-finalize-dialog.component';
import { BreadcrumbItem } from '@app/ui/misc/breadcrumb/definition/breadcrumb-item';
import { BaseComponent } from '@common/base/base.component';
import { TranslateService } from '@ngx-translate/core';
import * as FileSaver from 'file-saver';
import { Observable, of as observableOf } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { Role } from "@app/core/common/enum/role";

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

	dmp: DmpOverviewModel;
	isNew = true;
	isFinalized = false;
	isPublicView = true;
	hasPublishButton: boolean = true;
	breadCrumbs: Observable<BreadcrumbItem[]> = observableOf();
	isUserOwner: boolean;

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

	ngOnInit() {
		// Gets dmp data using parameter id
		this.route.params
			.pipe(takeUntil(this._destroyed))
			.subscribe((params: Params) => {
				const itemId = params['id'];
				const publicId = params['publicId'];
				if (itemId != null) {
					this.isNew = false;
					this.isPublicView = false;
					this.dmpService.getOverviewSingle(itemId)
						.pipe(takeUntil(this._destroyed))
						.subscribe(data => {
							this.dmp = data;
							this.setIsUserOwner();
							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/overview/' + this.dmp.id });
							this.breadCrumbs = observableOf(breadCrumbs);
						}, (error: any) => {
							if (error.status === 404) {
								return this.onFetchingDeletedCallbackError('/plans/');
							}
						});
				}
				else if (publicId != null) {
					this.isNew = false;
					this.isFinalized = true;
					this.isPublicView = true;
					this.dmpService.getOverviewSinglePublic(publicId)
						.pipe(takeUntil(this._destroyed))
						.subscribe(data => {
							this.dmp = data;
							this.setIsUserOwner();
							const breadCrumbs = [];
							breadCrumbs.push({ parentComponentName: null, label: this.language.instant('NAV-BAR.PUBLIC-DMPS'), url: "/explore-plans" });
							breadCrumbs.push({ parentComponentName: 'DmpListingComponent', label: this.dmp.label, url: '/plans/publicOverview/' + this.dmp.id });
							this.breadCrumbs = observableOf(breadCrumbs);
						}, (error: any) => {
							if (error.status === 404) {
								return this.onFetchingDeletedCallbackError('/plans/');
							}
						});
				}
			});
	}

	onFetchingDeletedCallbackError(redirectRoot: string) {
		this.uiNotificationService.snackBarNotification(this.language.instant('DMP-OVERVIEW.ERROR.DELETED-DMP'), SnackBarNotificationLevel.Error);
		this.router.navigate([redirectRoot]);
	}

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

	editClicked(dmp: DmpOverviewModel) {
		this.router.navigate(['/plans/edit/' + dmp.id]);
	}

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

	grantClicked(grantId: String) {
		// ----------- UNCOMMENT TO ADD AGAIN GRANTS --------
		// this.router.navigate(['/grants/edit/' + grantId]);
	}

	datasetClicked(datasetId: String) {
		if (this.isPublicView) {
			this.router.navigate(['/datasets/publicEdit/' + datasetId]);
		} else {
			this.router.navigate(['/datasets/edit/' + datasetId]);
		}
	}

	datasetsClicked(dmpId: String) {
		if (!this.isFinalized)
			this.router.navigate(['/plans/edit/' + dmpId], { queryParams: { tab: "datasetDescriptions" } });
		else
			this.router.navigate(['/explore'], { queryParams: { dmpId: dmpId } });
	}

	goToUri(uri: string) {
		window.open(uri, "_blank");
	}

	deleteClicked() {
		const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
			maxWidth: '300px',
			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)
					);
			}
		});
	}

	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(['/plans']);
	}

	onDeleteCallbackError(error) {
		this.uiNotificationService.snackBarNotification(error.error.message ? error.error.message : this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-DELETE'), SnackBarNotificationLevel.Error);
	}

	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;
	}

	roleDisplayFromList(value: UserInfoListingModel[]) {
		const principal: Principal = this.authentication.current();
		let role: number;
		if (principal) {
			value.forEach(element => {
				if (principal.id === element.id) {
					role = element.role;
				}
			});
		}
		if (role === Role.Owner) {
			return this.translate.instant('DMP-LISTING.OWNER');
		} else if (role === Role.Member) {
			return this.translate.instant('DMP-LISTING.MEMBER');
		} else {
			return this.translate.instant('DMP-LISTING.OWNER');
		}
	}

	isUserDMPRelated() {
		const principal: Principal = this.authentication.current();
		let isRelated: boolean = false;
		if (this.dmp && principal) {
			this.dmp.users.forEach(element => {
				if (element.id === principal.id) {
					isRelated = true;
				}
			})
		}
		return isRelated;
	}

	roleDisplay(value: UserInfoListingModel) {
		if (value.role === Role.Member) {
			return this.translate.instant('DMP-LISTING.MEMBER');
		} else {
			return this.translate.instant('DMP-LISTING.OWNER');
		}
	}

	isDraftDataset(dataset: DatasetOverviewModel) {
		return dataset.status == DatasetStatus.Draft;
	}

	isDraftDmp(dmp: DmpOverviewModel) {
		return dmp.status == DmpStatus.Draft;
	}

	isFinalizedDmp(dmp: DmpOverviewModel) {
		return dmp.status == DmpStatus.Finalized;
	}

	isPublishedDMP(dmp: DmpOverviewModel) {
		return (dmp.status == DmpStatus.Finalized && dmp.isPublic);
	}

	hasDoi(dmp: DmpOverviewModel) {
		return dmp.doi == null ? true : false;
	}

	getDoi(dmp: DmpOverviewModel) {
		const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
			maxWidth: '600px',
			restoreFocus: false,
			data: {
				message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ZENODO-DOI'),
				confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CONFIRM'),
				cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL'),
			}
		});
		dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
			if (result) {
				this.dmpService.getDoi(dmp.id)
					.pipe(takeUntil(this._destroyed))
					.subscribe(
						complete => {
							this.onDOICallbackSuccess();
							this.dmp.doi = complete;
						},
						error => this.onDeleteCallbackError(error)
					);
			}
		});
	}

	onDOICallbackSuccess(): void {
		this.uiNotificationService.snackBarNotification(this.language.instant('DMP-EDITOR.SNACK-BAR.SUCCESSFUL-DOI'), SnackBarNotificationLevel.Success);
	}

	onDOICallbackError(error) {
		this.uiNotificationService.snackBarNotification(error.error.message ? error.error.message : this.language.instant('DMP-EDITOR.SNACK-BAR.UNSUCCESSFUL-DOI'), SnackBarNotificationLevel.Error);
	}

	showPublishButton(dmp: DmpOverviewModel) {
		return this.isFinalizedDmp(dmp) && !dmp.isPublic && this.hasPublishButton;
	}

	publish(dmpId: String) {
		const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
			maxWidth: '500px',
			restoreFocus: false,
			data: {
				message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.PUBLISH-ITEM'),
				privacyPolicyNames: this.language.instant('GENERAL.CONFIRMATION-DIALOG.PRIVACY-POLICY-NAMES'),
				confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CONFIRM'),
				cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL'),
				isDeleteConfirmation: false
			}
		});
		dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
			if (result) {
				this.dmpService.publish(dmpId)
					.pipe(takeUntil(this._destroyed))
					.subscribe(() => { this.hasPublishButton = false });
			}
		});
	}

	finalize(dmp: DmpOverviewModel) {

		const dialogInputModel: DmpFinalizeDialogInput = {
			dmpLabel: this.dmp.label,
			dmpDescription: this.dmp.description,
			datasets: this.dmp.datasets.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: DmpFinalizeDialogOutput) => {
			if (result && !result.cancelled) {
				var datasetsToBeFinalized: DatasetsToBeFinalized = {
					uuids: result.datasetsToBeFinalized
				};
				this.dmpService.finalize(datasetsToBeFinalized, this.dmp.id)
					.pipe(takeUntil(this._destroyed))
					.subscribe(
						complete => {
							this.dmp.status = DmpStatus.Finalized;
							this.onCallbackSuccess()
						},
						error => this.onFinalizeCallbackError(error)
					);
			}
		});
	}

	onFinalizeCallbackError(error) {
		this.uiNotificationService.snackBarNotification(error.error.message ? error.error.message : this.language.instant('DMP-EDITOR.SNACK-BAR.UNSUCCESSFUL-FINALIZE'), SnackBarNotificationLevel.Error);
	}

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

	viewVersions(rowId: String, rowLabel: String) {
		if (this.dmp.isPublic && !this.isUserOwner) {
			this.router.navigate(['/explore-plans/versions/' + rowId], { queryParams: { groupLabel: rowLabel } });
		} else {
			this.router.navigate(['/plans/versions/' + rowId], { queryParams: { groupLabel: rowLabel } });
		}
	}

	public isAuthenticated(): boolean {
		return !(!this.authentication.current());
	}

	// 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);
	// 		}
	// 	});
	// }

	// advancedClickedFinalized() {
	// 	const dialogRef = this.dialog.open(ExportMethodDialogComponent, {
	// 		maxWidth: '250px',
	// 		data: {
	// 			message: "Download as:",
	// 			documentButton: "Document",
	// 			pdfButton: "PDF",
	// 			isFinalized: true
	// 		}
	// 	});
	// 	dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
	// 		if (result == "pdf") {
	// 			this.downloadPDF(this.dmp.id);
	// 		} else if (result == "doc") {
	// 			this.downloadDocx(this.dmp.id);
	// 		}
	// 	});
	// }

}
