import { DataSource } from '@angular/cdk/table';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { Component, OnInit, ViewChild } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { MatPaginator, PageEvent } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { ActivatedRoute, Params, Router } from '@angular/router';
import { DatasetStatus } from '@app/core/common/enum/dataset-status';
import { DataTableRequest } from '@app/core/model/data-table/data-table-request';
import { DatasetListingModel } from '@app/core/model/dataset/dataset-listing';
import { DmpModel } from '@app/core/model/dmp/dmp';
import { DatasetProfileCriteria } from '@app/core/query/dataset-profile/dataset-profile-criteria';
import { DatasetProfileService } from '@app/core/services/dataset-profile/dataset-profile.service';
import { DmpService } from '@app/core/services/dmp/dmp.service';
import { MatomoService } from '@app/core/services/matomo/matomo-service';
import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service';
import { DatasetProfileCriteriaComponent } from '@app/ui/admin/dataset-profile/listing/criteria/dataset-profile.component';
import { BreadcrumbItem } from '@app/ui/misc/breadcrumb/definition/breadcrumb-item';
import { BaseComponent } from '@common/base/base.component';
import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component';
import { TranslateService } from '@ngx-translate/core';
import * as FileSaver from 'file-saver';
import { merge as observableMerge, Observable, of as observableOf } from 'rxjs';
import { map, startWith, switchMap, takeUntil } from 'rxjs/operators';
import { DialogConfirmationUploadDatasetProfiles } from './criteria/dialog-confirmation-upload-profile/dialog-confirmation-upload-profiles.component';

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

	@ViewChild(MatPaginator, { static: true }) _paginator: MatPaginator;
	@ViewChild(MatSort, { static: true }) sort: MatSort;
	@ViewChild(DatasetProfileCriteriaComponent, { static: true }) criteria: DatasetProfileCriteriaComponent;

	breadCrumbs: Observable<BreadcrumbItem[]>;
	dataSource: DatasetDataSource | null;
	displayedColumns: String[] = ['label', 'description', 'created', 'status', 'actions'];
	pageEvent: PageEvent;
	titlePrefix: String;
	dmpId: String;
	itemId: string;
	datasetStatusEnum = DatasetStatus;

	constructor(
		private datasetService: DatasetProfileService,
		private router: Router,
		private route: ActivatedRoute,
		private dmpService: DmpService,
		private language: TranslateService,
		private uiNotificationService: UiNotificationService,
		private httpClient: HttpClient,
		private matomoService: MatomoService,
		private dialog: MatDialog,
		private datasetProfileService: DatasetProfileService,
	) {
		super();
	}

	ngOnInit() {
		this.matomoService.trackPageView('Admin: Dataset Templates');
		this.route.params
			.pipe(takeUntil(this._destroyed))
			.subscribe((params: Params) => {
				if (params['dmpId']) {
					this.dmpId = params['dmpId'];
					if (this.dmpId != null) { this.setDmpTitle(this.dmpId); }
					this.criteria.setCriteria(this.getDefaultCriteria());
					this.refresh();
					this.criteria.setRefreshCallback(() => this.refresh());
					// this.breadCrumbs = Observable.of([{
					// 	parentComponentName: null,
					// 	label: this.language.instant('NAV-BAR.DATASET-TEMPLATES'),
					// 	url: 'plans/edit/' + this.dmpId
					// }]);
				} else {
					this.itemId = params['groupId'];
					if (this.itemId) {
						const datasetProfileLabel = this.route.snapshot.queryParams.groupLabel;
					}
					this.criteria.setCriteria(this.getDefaultCriteria());
					this.refresh();
					this.criteria.setRefreshCallback(() => this.refresh());
					this.breadCrumbs = observableOf([{
						parentComponentName: null,
						label: this.language.instant('NAV-BAR.DATASET-TEMPLATES'),
						url: '/dataset-profiles'
					}]);
				}
			});
	}

	setDmpTitle(dmpId: String) {
		this.dmpService.getSingle(dmpId).pipe(map(data => data as DmpModel))
			.pipe(takeUntil(this._destroyed))
			.subscribe(data => {
				this.titlePrefix = data.label;
			}
			);
	}

	refresh() {
		this.dataSource = new DatasetDataSource(this.datasetService, this._paginator, this.sort, this.criteria, this.itemId);
		this._paginator.pageIndex = 0;
	}

	rowClick(rowId: String) {
		this.router.navigate(['dataset-profiles/' + rowId]);
	}

	getDefaultCriteria(): DatasetProfileCriteria {
		const defaultCriteria = new DatasetProfileCriteria();
		return defaultCriteria;
	}

	clone(id: string) {
		this.router.navigate(['dataset-profiles/clone/' + id]);
	}

	newVersion(id: string, label: string) {
		this.router.navigate(['dataset-profiles/newversion/' + id]);
	}

	viewVersions(rowId, rowLabel) {
		this.router.navigate(['/dataset-profiles/versions/' + rowId], { queryParams: { groupLabel: rowLabel } });
	}
	downloadXML(datasetProfileId: string): void {
		this.datasetProfileService.downloadXML(datasetProfileId)
			.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;
	}

	deleteTemplate(id: string){
		if(id){
			const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
				restoreFocus: false,
				data: {
					message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.DELETE-ITEM'),
					confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CONFIRM'),
					cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL'),
					isDeleteConfirmation: true
				}
			});

			dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
				if (result) {
					//this.form.get('status').setValue(DatasetProfileEnum.DELETED);
					this.datasetProfileService.delete(id, null)
						.pipe(takeUntil(this._destroyed))
						.subscribe(
							complete => {
								this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-DATASET-PROFILE-DELETE'), SnackBarNotificationLevel.Success);
								this.refresh();
							},
							error => {
								this.onCallbackError(error);
								if (error.error.statusCode == 674) {
									this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-DATASET-PROFILE-DELETE'), SnackBarNotificationLevel.Error);
								} else {
									this.uiNotificationService.snackBarNotification(this.language.instant(error.message), SnackBarNotificationLevel.Error);
								}
							}
						);
				}
			});


		}
	}

	onCallbackError(errorResponse: HttpErrorResponse) {
		this.uiNotificationService.snackBarNotification(errorResponse.message, SnackBarNotificationLevel.Warning);
	}
	// makeItPublic(id: String) {
	//   debugger;
	//   this.datasetService.makeDatasetPublic(id).pipe(takeUntil(this._destroyed)).subscribe();
	// }

	openDialog(): void {
		const dialogRef = this.dialog.open(DialogConfirmationUploadDatasetProfiles, {
			width: '500px',
			restoreFocus: false,
			data: {
				message: this.language.instant('DATASET-WIZARD.UPLOAD.UPLOAD-XML-FILE-TITLE'),
				confirmButton: this.language.instant('DATASET-WIZARD.UPLOAD.UPLOAD-XML'),
				cancelButton: this.language.instant('DATASET-WIZARD.UPLOAD.UPLOAD-XML-FILE-CANCEL'),
				name: "",
				file: FileList,
				sucsess: false
			}
		});
		dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(data => {
			if (data && data.sucsess && data.name != null && data.file != null) {
				this.datasetService.uploadFile(data.file, data.name)
					.pipe(takeUntil(this._destroyed))
					.subscribe(_=>{
						this.uiNotificationService.snackBarNotification('Template successfully uploaded', SnackBarNotificationLevel.Success);
						this.refresh();
					},
					error=>{
						this.uiNotificationService.snackBarNotification(error.message, SnackBarNotificationLevel.Error);
					}
					);
			}
		});
	}

	/**
	 * gets as a a pameter a number representing the status and returns the class that is applied
	 * to status-chip */
	getStatusClass(status: DatasetStatus):string{
		
		if(status == DatasetStatus.Finalized){
			return 'status-chip-finalized'
		}

		return 'status-chip-draft';
	}

}

export class DatasetDataSource extends DataSource<DatasetListingModel> {

	totalCount = 0;

	constructor(
		private _service: DatasetProfileService,
		private _paginator: MatPaginator,
		private _sort: MatSort,
		private _criteria: DatasetProfileCriteriaComponent,
		private itemId
	) {
		super();

	}

	connect(): Observable<DatasetListingModel[]> {
		const displayDataChanges = [
			this._paginator.page
			//this._sort.matSortChange
		];

		return observableMerge(...displayDataChanges).pipe(
			startWith(null),
			switchMap(() => {
				const startIndex = this._paginator.pageIndex * this._paginator.pageSize;
				let fields: Array<string> = new Array();
				if (this._sort.active) { fields = this._sort.direction === 'asc' ? ['+' + this._sort.active] : ['-' + this._sort.active]; }
				const request = new DataTableRequest<DatasetProfileCriteria>(startIndex, this._paginator.pageSize, { fields: fields });
				request.criteria = this._criteria.criteria;
				request.criteria.finalized = false;
				if (this.itemId) {
					request.criteria.groupIds = [this.itemId];
					request.criteria.allVersions = true;
				}
				return this._service.getPaged(request);
			}),
			/*.catch((error: any) => {
			  this._snackBar.openFromComponent(SnackBarNotificationComponent, {
				data: { message: 'GENERAL.SNACK-BAR.FORMS-BAD-REQUEST', language: this._languageService },
				duration: 3000,
				extraClasses: ['snackbar-warning']
			  });
			  //this._criteria.criteria.onCallbackError(error);
			  return Observable.of(null);
			})*/
			map(result => {
				return result;
			}),
			map(result => {
				if (!result) { return []; }
				// if (this._paginator.pageIndex === 0) { this.totalCount = result.totalCount; }
				this.totalCount = result.totalCount;
				return result.data;
			}));
	}

	disconnect() {
		// No-op
	}
}
