
import { of as observableOf, Observable } from 'rxjs';
import { HttpErrorResponse } from '@angular/common/http';
import { Component, OnInit, ViewChild } from '@angular/core';
import { FormArray, FormControl, FormGroup } from '@angular/forms';
import { MatDialog } from '@angular/material/dialog';
import { MatHorizontalStepper } from '@angular/material/stepper';
import { ActivatedRoute, ParamMap, Router } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
import { map, takeUntil } from 'rxjs/operators';
import * as FileSaver from 'file-saver';
import { BaseComponent } from '@common/base/base.component';
import { DatasetProfileEditorModel } from '@app/ui/admin/dataset-profile/editor/dataset-profile-editor-model';
import { DatasetWizardModel } from '@app/core/model/dataset/dataset-wizard';
import { BreadcrumbItem } from '@app/ui/misc/breadcrumb/definition/breadcrumb-item';
import { DatasetProfileService } from '@app/core/services/dataset-profile/dataset-profile.service';
import { LoggingService } from '@app/core/services/logging/logging-service';
import { UiNotificationService, SnackBarNotificationLevel } from '@app/core/services/notification/ui-notification-service';
import { DatasetProfile } from '@app/core/model/admin/dataset-profile/dataset-profile';
import { DatasetProfileEnum } from '@app/core/common/enum/dataset-profile';
import { SectionEditorModel } from '@app/ui/admin/dataset-profile/admin/section-editor-model';
import { PageEditorModel } from '@app/ui/admin/dataset-profile/admin/page-editor-model';
import { DatasetStatus } from '@app/core/common/enum/dataset-status';
import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component';

const skipDisable: any[] = require('../../../../../assets/resources/skipDisable.json');

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

	isNew = true;
	isNewVersion = false;
	isClone = false;
	isDeleted = false;
	dataModel: DatasetProfileEditorModel;
	form: FormGroup;
	previewerFormGroup: FormGroup;
	private datasetProfileId: string;
	newVersionId: string;
	dataWizardModel: DatasetWizardModel;
	breadCrumbs: Observable<BreadcrumbItem[]>;
	@ViewChild('stepper', { static: false }) stepper: MatHorizontalStepper;
	viewOnly = false;

	constructor(
		private datasetProfileService: DatasetProfileService,
		private route: ActivatedRoute,
		private router: Router,
		private logger: LoggingService,
		private uiNotificationService: UiNotificationService,
		private language: TranslateService,
		private dialog: MatDialog
	) {
		super();
		// this.profileID = route.snapshot.params['id'];
		// this.cloneId = route.snapshot.params['cloneid'];
	}

	ngOnInit() {
		this.route.paramMap.pipe(takeUntil(this._destroyed)).subscribe((paramMap: ParamMap) => {
			this.datasetProfileId = paramMap.get('id');
			const cloneId = paramMap.get('cloneid');
			this.newVersionId = paramMap.get('newversionid');

			if (this.datasetProfileId != null) {
				this.isNew = false;
				this.datasetProfileService.getDatasetProfileById(this.datasetProfileId)
					.pipe(map(data => data as DatasetProfile), takeUntil(this._destroyed))
					.subscribe(
						data => {
							try {
								this.dataModel = new DatasetProfileEditorModel().fromModel(data);
								// this.isDeleted = this.masterItem.isActive === IsActive.Inactive;
								if (this.dataModel.status === DatasetProfileEnum.FINALIZED) {
									this.form = this.dataModel.buildForm(true, skipDisable);
									this.viewOnly = true;
								} else {
									this.form = this.dataModel.buildForm();
								}
								this.prepareForm();
							} catch {
								this.logger.error('Could not parse MasterItem: ' + data);
								this.uiNotificationService.snackBarNotification(this.language.instant('NOTIFICATIONS.DEFAULT.ERROR'), SnackBarNotificationLevel.Error);
							}
						},
						error => this.onCallbackError(error)
					);
				this.breadCrumbs = observableOf([{
					parentComponentName: 'DatasetProfileListingComponent',
					label: this.language.instant('NAV-BAR.TEMPLATE'),
					url: '/dataset-profiles/' + this.datasetProfileId
				}]);
			} else if (cloneId != null) {
				this.isClone = true;
				this.datasetProfileService.clone(cloneId)
					.pipe(map(data => data as DatasetProfile), takeUntil(this._destroyed))
					.subscribe(
						data => {
							try {
								this.dataModel = new DatasetProfileEditorModel().fromModel(data);
								// this.isDeleted = this.masterItem.isActive === IsActive.Inactive;
								this.dataModel.status = DatasetProfileEnum.SAVED;
								this.form = this.dataModel.buildForm();
								this.prepareForm();
							} catch {
								this.logger.error('Could not parse MasterItem: ' + data);
								this.uiNotificationService.snackBarNotification(this.language.instant('NOTIFICATIONS.DEFAULT.ERROR'), SnackBarNotificationLevel.Error);
							}
						},
						error => this.onCallbackError(error)
					);
			} else if (this.newVersionId != null) {
				this.isNewVersion = true;
				this.datasetProfileService.getDatasetProfileById(this.newVersionId)
					.pipe(map(data => data as DatasetProfile), takeUntil(this._destroyed))
					.subscribe(
						data => {
							try {
								this.dataModel = new DatasetProfileEditorModel().fromModel(data);
								// this.isDeleted = this.masterItem.isActive === IsActive.Inactive;
								this.form = this.dataModel.buildForm();
								this.form.get('version').setValue(this.form.get('version').value + 1);
								this.form.controls['label'].disable();
								this.form.controls['description'].disable();
								this.prepareForm();
							} catch {
								this.logger.error('Could not parse MasterItem: ' + data);
								this.uiNotificationService.snackBarNotification(this.language.instant('NOTIFICATIONS.DEFAULT.ERROR'), SnackBarNotificationLevel.Error);
							}
						},
						error => this.onCallbackError(error)
					);
			} else {
				this.dataModel = new DatasetProfileEditorModel();
				this.form = this.dataModel.buildForm();
				if (this.dataModel.status === DatasetProfileEnum.FINALIZED) {
					this.form.disable();
					this.viewOnly = true;
				}
				this.addSection();
				this.addPage();
			}
		});
	}

	prepareForm() {
		this.form.valueChanges
			.pipe(takeUntil(this._destroyed))
			.subscribe(change => {
				// this.datasetProfileService.preview(this.form.value)
				// 	.pipe(takeUntil(this._destroyed))
				// 	.subscribe(dataset => {
				// 		const datasetModel = new DatasetWizardModel();
				// 		datasetModel.datasetProfileDefinition = JsonSerializer.fromJSONObject(dataset, DatasetProfileDefinitionModel);
				// 		this.dataWizardModel = datasetModel;
				// 		this.previewerFormGroup = <FormGroup>this.dataWizardModel.buildForm().get('datasetProfileDefinition');
				// 	});
			});
		this.form.updateValueAndValidity();
	}

	onIsMultiplicityEnabledChange(isMultiplicityEnabled: boolean) {
		if (!isMultiplicityEnabled) {
			(<FormControl>this.form.get('multiplicity').get('min')).setValue(0);
			(<FormControl>this.form.get('multiplicity').get('max')).setValue(0);
		}
	}

	addSection() {
		const section: SectionEditorModel = new SectionEditorModel();
		this.dataModel.sections.push(section);
		(<FormArray>this.form.get('sections')).push(section.buildForm());
	}

	addPage() {
		const page: PageEditorModel = new PageEditorModel(this.dataModel.pages.length);
		this.dataModel.pages.push(page);
		(<FormArray>this.form.get('pages')).push(page.buildForm());
	}

	DeleteSection(index) {
		this.dataModel.sections.splice(index, 1);
		(<FormArray>this.form.get('sections')).removeAt(index);
	}

	onSubmit() {
		let data = this.form.value;
		if (this.datasetProfileId) {
			this.datasetProfileService.updateForm(this.datasetProfileId, data)
				.pipe(takeUntil(this._destroyed))
				.subscribe(() => {
					this.router.navigate(['/dataset-profiles']);
				});
		} else if (this.newVersionId) {
			data.label = this.form.get('label').value;
			data.description = this.form.get('description').value;
			this.datasetProfileService.newVersion(this.newVersionId, data)
				.pipe(takeUntil(this._destroyed))
				.subscribe(() => {
					this.router.navigate(['/dataset-profiles']);
				},
					error => this.onCallbackErrorNewVersion(error)
				);
		} else {
			this.form.get('status').setValue(DatasetStatus.Draft);
			data = this.form.value;
			this.datasetProfileService.createForm(data)
				.pipe(takeUntil(this._destroyed))
				.subscribe(() => {
					this.router.navigate(['/dataset-profiles']);
				});
		}
	}

	finalize() {
		//const data = this.form.value;
		this.form.get('status').setValue(DatasetProfileEnum.FINALIZED);

		this.onSubmit();
	}

	updateFinalized() {
		this.datasetProfileService.updateForm(this.datasetProfileId, this.form.getRawValue())
			.pipe(takeUntil(this._destroyed))
			.subscribe(() => {
				this.router.navigate(['/dataset-profiles']);
			});
	}

	showUpdateButton() {
		return !this.isNew && this.dataModel.status === DatasetProfileEnum.FINALIZED;
	}

	isStepActive(step: number) {
		return this.stepper && this.stepper.selectedIndex === step;
	}

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

	onCallbackErrorNewVersion(errorResponse: HttpErrorResponse) {
		this.uiNotificationService.snackBarNotification(errorResponse.error.message, SnackBarNotificationLevel.Error);
	}

	onCallbackError(errorResponse: HttpErrorResponse) {
		// const error: HttpError = this.httpErrorHandlingService.getError(errorResponse);
		// if (error.statusCode === 400) {
		// 	this.masterItem.validationErrorModel.fromJSONObject(errorResponse.error);
		// 	this.formService.validateAllFormFields(this.formGroup);
		// } else {
		this.uiNotificationService.snackBarNotification(errorResponse.message, SnackBarNotificationLevel.Warning);
		// }
	}

	// DELETE Function
	public delete(): void {
		if (this.datasetProfileId && !this.isNew) {
			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(this.datasetProfileId, this.form.value)
						.pipe(takeUntil(this._destroyed))
						.subscribe(
							complete => {
								this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-DATASET-PROFILE-DELETE'), SnackBarNotificationLevel.Success);
								this.router.navigate(['/dataset-profiles']);
							},
							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);
								}
							}
						);
				}
			});
		}
	}

	downloadXML(): void {
		this.datasetProfileService.downloadXML(this.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;
	}
}
