import { Component, OnInit } from '@angular/core';
import { BaseComponent } from '@common/base/base.component';
import { DatasetOverviewModel } from '@app/core/model/dataset/dataset-overview';
import { BreadcrumbItem } from '@app/ui/misc/breadcrumb/definition/breadcrumb-item';
import { Observable, of as observableOf } from 'rxjs';
import { ActivatedRoute, Router, Params } from '@angular/router';
import { DatasetService } from '@app/core/services/dataset/dataset.service';
import { TranslateService } from '@ngx-translate/core';
import { AuthService } from '@app/core/services/auth/auth.service';
import { MatDialog } from '@angular/material/dialog';
import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service';
import { ConfigurationService } from '@app/core/services/configuration/configuration.service';
import { Oauth2DialogService } from '@app/ui/misc/oauth2-dialog/service/oauth2-dialog.service';
import { UserService } from '@app/core/services/user/user.service';
import { filter, takeUntil } from 'rxjs/operators';
import { Principal } from '@app/core/model/auth/principal';
import { Role } from '@app/core/common/enum/role';
import { Location } from '@angular/common';
import { UserInfoListingModel } from '@app/core/model/user/user-info-listing';
import { DatasetStatus } from '@app/core/common/enum/dataset-status';
import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component';
import * as FileSaver from 'file-saver';
import { DmpInvitationDialogComponent } from '@app/ui/dmp/invitation/dmp-invitation-dialog.component';
import { DatasetWizardEditorModel } from '../dataset-wizard/dataset-wizard-editor.model';
import { DatasetWizardService } from '@app/core/services/dataset-wizard/dataset-wizard.service';
import { FormControl } from '@angular/forms';
import { DatasetCopyDialogueComponent } from '../dataset-wizard/dataset-copy-dialogue/dataset-copy-dialogue.component';
import { DmpService } from '@app/core/services/dmp/dmp.service';
import { ResearcherModel } from '@app/core/model/researcher/researcher';
import { LockService } from '@app/core/services/lock/lock.service';
import { DatasetWizardModel } from '@app/core/model/dataset/dataset-wizard';
import { DmpStatus } from '@app/core/common/enum/dmp-status';
import { DmpOverviewModel } from '@app/core/model/dmp/dmp-overview';
import { MatomoService } from '@app/core/services/matomo/matomo-service';
import { HttpClient } from '@angular/common/http';
import { PopupNotificationDialogComponent } from '@app/library/notification/popup/popup-notification.component';


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

	dataset: DatasetOverviewModel;
	// datasetWizardEditorModel: DatasetWizardEditorModel;
	datasetWizardModel: DatasetWizardModel;
	isNew = true;
	isFinalized = false;
	isPublicView = true;
	hasPublishButton: boolean = true;
	breadCrumbs: Observable<BreadcrumbItem[]> = observableOf();
	isUserOwner: boolean;
	expand = false;
	hasDOIToken = false;
	researchers: ResearcherModel[];
	users: UserInfoListingModel[];
	lockStatus: Boolean;

	constructor(
		private route: ActivatedRoute,
		private router: Router,
		private datasetService: DatasetService,
		private translate: TranslateService,
		private authentication: AuthService,
		private dialog: MatDialog,
		private language: TranslateService,
		private uiNotificationService: UiNotificationService,
		private configurationService: ConfigurationService,
		private oauth2DialogService: Oauth2DialogService,
		private userService: UserService,
		private dmpService: DmpService,
		private location: Location,
		private datasetWizardService: DatasetWizardService,
		private lockService: LockService,
		private httpClient: HttpClient,
		private matomoService: MatomoService
	) {
		super();
	}

	ngOnInit() {
		this.matomoService.trackPageView('Dataset Overview');
		// Gets dataset 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.datasetService.getOverviewSingle(itemId)
						.pipe(takeUntil(this._destroyed))
						.subscribe(data => {
							this.dataset = data;
							this.researchers = this.dataset.dmp.researchers;
							this.users = this.dataset.dmp.users;
							this.checkLockStatus(this.dataset.id);
							this.setIsUserOwner();
							const breadCrumbs = [];
							breadCrumbs.push({ parentComponentName: null, label: this.language.instant('NAV-BAR.MY-DATASET-DESCRIPTIONS'), url: "/datasets" });
							breadCrumbs.push({ parentComponentName: 'DatasetListingComponent', label: this.dataset.label, url: '/datasets/overview/' + this.dataset.id });
							this.breadCrumbs = observableOf(breadCrumbs);
						}, (error: any) => {
							if (error.status === 404) {
								return this.onFetchingDeletedCallbackError('/datasets/');
							}
							if (error.status === 403) {
								return this.onFetchingForbiddenCallbackError('/datasets/');
							}
						});
				}
				else if (publicId != null) {
					this.isNew = false;
					this.isFinalized = true;
					this.isPublicView = true;
					this.datasetService.getOverviewSinglePublic(publicId)
						.pipe(takeUntil(this._destroyed))
						.subscribe(data => {
							this.dataset = data;
							this.researchers = this.dataset.dmp.researchers;
							this.users = this.dataset.dmp.users;
							const breadCrumbs = [];
							breadCrumbs.push({ parentComponentName: null, label: this.language.instant('NAV-BAR.PUBLIC DATASETS'), url: "/explore" });
							breadCrumbs.push({ parentComponentName: 'DatasetListingComponent', label: this.dataset.label, url: '/datasets/publicOverview/' + this.dataset.id });
							this.breadCrumbs = observableOf(breadCrumbs);
						}, (error: any) => {
							if (error.status === 404) {
								return this.onFetchingDeletedCallbackError('/explore');
							}
							if (error.status === 403) {
								return this.onFetchingForbiddenCallbackError('/explore');
							}
						});
				}
			});
	}

	checkLockStatus(id: string) {
		this.lockService.checkLockStatus(id).pipe(takeUntil(this._destroyed))
			.subscribe(lockStatus => {
				this.lockStatus = lockStatus
				if(lockStatus){
					this.dialog.open(PopupNotificationDialogComponent,{data:{
						title:this.language.instant('DATASET-OVERVIEW.LOCKED.TITLE'),
						message:this.language.instant('DATASET-OVERVIEW.LOCKED.MESSAGE')
					}, maxWidth:'30em'});
				}
			});
	}

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

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

	goBack(): void {
		this.location.back();
	}

	reloadPage(): void {
		const path = this.location.path();
		this.router.navigateByUrl('/reload', { skipLocationChange: true }).then(() => this.router.navigate([path]));
	}

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

	isUserAuthor(userId: string): boolean {
		if (this.isAuthenticated()) {
			const principal: Principal = this.authentication.current();
			return userId === principal.id;
		} else return false;
	}

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

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


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

	openShareDialog(rowId: any, rowName: any) {
		const dialogRef = this.dialog.open(DmpInvitationDialogComponent, {
			autoFocus: false,
			restoreFocus: false,
			data: {
				dmpId: rowId,
				dmpName: rowName
			}
		});
	}

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

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

	isFinalizedDataset(dataset: DatasetOverviewModel) {
		return dataset.status == DatasetStatus.Finalized;
	}

	editClicked(dataset: DatasetOverviewModel) {
		if (dataset.public) {
			this.router.navigate(['/datasets/publicEdit/', dataset.id]);
			// let url = this.router.createUrlTree(['/datasets/publicEdit/', dataset.id]);
			// window.open(url.toString(), '_blank');
		} else {
			this.router.navigate(['/datasets/edit/', dataset.id]);
			// let url = this.router.createUrlTree(['/datasets/edit/', dataset.id]);
			// let url = this.router.createUrlTree(['/plans/edit/', dataset.dmp.id], { queryParams: { dataset: dataset.id } });
			// window.open(url.toString(), '_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.datasetService.delete(this.dataset.id)
					.pipe(takeUntil(this._destroyed))
					.subscribe(
						complete => {
							this.onDeleteCallbackSuccess();
						},
						error => this.onDeleteCallbackError(error)
					);
			}
		});
	}

	dmpClicked(dmp: DmpOverviewModel) {
		if (this.isPublicView) {
			this.router.navigate(['/explore-plans/publicOverview/' + dmp.id]);
		} else {
			this.router.navigate(['/plans/overview/' + dmp.id]);
		}
	}

	onDeleteCallbackSuccess(): void {
		this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-DELETE'), SnackBarNotificationLevel.Success);
		this.router.navigate(['/datasets']);
	}

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

	onUpdateCallbackSuccess(): void {
		this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE'), SnackBarNotificationLevel.Success);
		this.reloadPage();
	}

	onUpdateCallbackError(error) {
		this.uiNotificationService.snackBarNotification(error.error.message ? this.tryTranslate( error.error.message) : this.language.instant('DATASET-UPLOAD.SNACK-BAR.UNSUCCESSFUL'), SnackBarNotificationLevel.Error);
	}
	tryTranslate(errorMessage: string): string{
		return errorMessage.replace('Field value of', this.language.instant('Field value of'))
			.replace('must be filled', this.language.instant('must be filled'));
	}

	public getOrcidPath(): string {
		return this.configurationService.orcidPath;
	}

	isOrcid(reference: string) {
		const head = reference.split(':')[0];
		return head === 'orcid';
	}

	getOrcidPathForResearcher(reference: string): string {
		const path = this.getOrcidPath();
		const userId = reference.split(':')[1];
		return path + userId;
	}

	downloadPDF(id: string) {
		this.datasetService.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);
			});
	}

	downloadDocx(id: string) {
		this.datasetService.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);
			});
	}

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

	//GK: NO
	//   downloadJson(id: string) {
	//     this.datasetService.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;
	}

	openDmpSearchDialogue() {
		const formControl = new FormControl();
		const dialogRef = this.dialog.open(DatasetCopyDialogueComponent, {
			width: '500px',
			restoreFocus: false,
			data: {
				formControl: formControl,
				datasetId: this.dataset.id,
				datasetProfileId: this.dataset.datasetTemplate.id,
				datasetProfileExist: false,
				confirmButton: this.language.instant('DATASET-WIZARD.DIALOGUE.COPY'),
				cancelButton: this.language.instant('DATASET-WIZARD.DIALOGUE.CANCEL')
			}
		});

		dialogRef.afterClosed().pipe(takeUntil(this._destroyed))
			.subscribe(result => {
				if (result && result.datasetProfileExist) {
					const newDmpId = result.formControl.value.id;
					this.router.navigate(['/datasets/copy/' + result.datasetId], { queryParams: { newDmpId: newDmpId } });
					// let url = this.router.createUrlTree(['/datasets/copy/', result.datasetId, { newDmpId: newDmpId }])
					// window.open(url.toString(), '_blank')
				}
			});
	}

	updateUsers() {
		return this.dmpService.updateUsers(this.dataset.dmp.id, this.users).pipe(takeUntil(this._destroyed))
			.subscribe(
				complete => {
					this.onUpdateCallbackSuccess();
				},
				error => this.onUpdateCallbackError(error)
			);
	}

	removeUserFromDmp(user: UserInfoListingModel) {
		const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
			data: {
				message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.DELETE-USER'),
				confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.REMOVE'),
				cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL'),
				isDeleteConfirmation: false
			}
		});
		dialogRef.afterClosed().subscribe(result => {
			if (result) {
				const index = this.users.findIndex(x => x.id === user.id);
				if (index > -1) {
					this.users.splice(index, 1);
				}
				this.updateUsers();
			}
		});
	}

	showPublishButton(dataset: DatasetOverviewModel) {
		return this.isFinalizedDataset(dataset) && !dataset.public && this.hasPublishButton;
	}

	// publish(id: 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.datasetService.publish(id)
	//         .pipe(takeUntil(this._destroyed))
	//         .subscribe(() => {
	//           this.hasPublishButton = false;
	//           this.reloadPage();
	//         });
	//     }
	//   });
	// }

	finalize(dataset: DatasetOverviewModel) {


		this.dialog.open(ConfirmationDialogComponent, {
			data: {
				message: this.language.instant('DATASET-OVERVIEW.FINALISE-POPUP.MESSAGE'),
				confirmButton: this.language.instant('DATASET-OVERVIEW.FINALISE-POPUP.CONFIRM'),
				cancelButton: this.language.instant('DATASET-OVERVIEW.FINALISE-POPUP.CANCEL'),
			},
			maxWidth: '30em'
		})
		.afterClosed()
		.pipe(
			filter(x => x),
			takeUntil(this._destroyed)
		)
		.subscribe( _ =>{
			this.router.navigate(['datasets','edit',dataset.id]);
		})





		// const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
		// 	restoreFocus: false,
		// 	data: {
		// 		message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.FINALIZE-ITEM'),
		// 		confirmButton: this.language.instant('QUICKWIZARD.SAVE-DIALOG.ACTIONS.AFFIRMATIVE'),
		// 		cancelButton: this.language.instant('QUICKWIZARD.SAVE-DIALOG.ACTIONS.NEGATIVE'),
		// 		isDeleteConfirmation: false
		// 	}
		// });
		// dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
		// 	if (result) {
		// 		this.datasetWizardService.getSingle(dataset.id)
		// 		.pipe(takeUntil(this._destroyed))
		// 		.subscribe(data => {
		// 			this.datasetWizardModel = data;
		// 			this.datasetWizardModel.status = DatasetStatus.Finalized;
		// 			this.datasetWizardService.createDataset(this.datasetWizardModel)
		// 			.pipe(takeUntil(this._destroyed))
		// 			.subscribe(
		// 				data => this.onUpdateCallbackSuccess(),
		// 				error => this.onUpdateCallbackError(error)
		// 			);
		// 		});
		// 	}
		// });
	}

	hasReversableStatus(dataset: DatasetOverviewModel): boolean {
		return dataset.dmp.status == DmpStatus.Draft && dataset.status == DatasetStatus.Finalized
	}

	reverse(dataset: DatasetOverviewModel) {
		const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
			restoreFocus: false,
			data: {
				message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.UNFINALIZE-ITEM'),
				confirmButton: this.language.instant('QUICKWIZARD.SAVE-DIALOG.ACTIONS.AFFIRMATIVE'),
				cancelButton: this.language.instant('QUICKWIZARD.SAVE-DIALOG.ACTIONS.NEGATIVE'),
				isDeleteConfirmation: false
			}
		});
		dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
			if (result) {
				this.datasetWizardService.getSingle(dataset.id)
				.pipe(takeUntil(this._destroyed))
				.subscribe(data => {
					this.datasetWizardModel = data;
					this.datasetWizardModel.status = DatasetStatus.Draft;
					this.datasetWizardService.createDataset(this.datasetWizardModel)
					.pipe(takeUntil(this._destroyed))
					.subscribe(
						data => this.onUpdateCallbackSuccess(),
						error => this.onUpdateCallbackError(error)
					);
				});
			}
		});
	}

}
