import { BaseComponent } from '@common/base/base.component';
import { OnInit, Component, Input, Output, EventEmitter } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { ConfigurationService } from '@app/core/services/configuration/configuration.service';
import { ExternalSourcesService } from '@app/core/services/external-sources/external-sources.service';
import { MatChipInputEvent } from '@angular/material/chips';
import { MatDialog } from '@angular/material/dialog';
import { MatSnackBar } from '@angular/material/snack-bar';
import { DatasetWizardService } from '@app/core/services/dataset-wizard/dataset-wizard.service';
import { ActivatedRoute, Router } from '@angular/router';
import { DmpService } from '@app/core/services/dmp/dmp.service';
import { ExternalSourcesConfigurationService } from '@app/core/services/external-sources/external-sources-configuration.service';
import { UiNotificationService, SnackBarNotificationLevel } from '@app/core/services/notification/ui-notification-service';
import { FormService } from '@common/forms/form-service';
import { LockService } from '@app/core/services/lock/lock.service';
import { AuthService } from '@app/core/services/auth/auth.service';
import { DatasetStatus } from '@app/core/common/enum/dataset-status';
import { FormGroup, FormControl, FormArray } from '@angular/forms';
import { DatasetDescriptionFormEditorModel } from '@app/ui/misc/dataset-description-form/dataset-description-form.model';
import { DatasetProfileModel } from '@app/core/model/dataset/dataset-profile';
import { LockModel } from '@app/core/model/lock/lock.model';
import { takeUntil, map, catchError } from 'rxjs/operators';
import { RequestItem } from '@app/core/query/request-item';
import { isNullOrUndefined } from '@app/utilities/enhancers/utils';
import { interval, Observable, of as observableOf } from 'rxjs';
import { Guid } from '@common/types/guid';
import { Location } from '@angular/common';
import { DatasetProfileCriteria } from '@app/core/query/dataset-profile/dataset-profile-criteria';
import { DmpListingModel } from '@app/core/model/dmp/dmp-listing';
import { DatasetWizardEditorModel, ExternalTagEditorModel } from '@app/ui/dataset/dataset-wizard/dataset-wizard-editor.model';
import { ENTER, COMMA } from '@angular/cdk/keycodes';
import { GuidedTour, Orientation } from '@app/library/guided-tour/guided-tour.constants';
import { GuidedTourService } from '@app/library/guided-tour/guided-tour.service';
import { MultipleAutoCompleteConfiguration } from '@app/library/auto-complete/multiple/multiple-auto-complete-configuration';
import { DataTableRequest } from '@app/core/model/data-table/data-table-request';
import { AvailableProfilesComponent } from '../available-profiles/available-profiles.component';


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

	viewOnly = false;
	editMode = false;
	// publicMode = false;

	// DatasetStatus = DatasetStatus;
	// dmpAutoCompleteConfiguration: SingleAutoCompleteConfiguration;

	datasetWizardModel: DatasetWizardEditorModel;
	// isNew = true;
	// isCopy = false;
	// formGroup: FormGroup = null;
	datasetProfileDefinitionModel: DatasetDescriptionFormEditorModel;

	// availableProfiles: DatasetProfileModel[] = [];
	// itemId: string;
	// publicId: string;
	// profileUpdateId: string;
	// downloadDocumentId: string;
	// isLinear = false;
	lock: LockModel;
	lockStatus: Boolean;
	dmpText: string = null;

	@Input() formGroup: FormGroup;
	@Input() dmpId: string;
	@Input() datasetId: string;
	@Input() availableProfiles: DatasetProfileModel[];
	@Output() formChanged: EventEmitter<any> = new EventEmitter();
	readonly separatorKeysCodes: number[] = [ENTER, COMMA];

	profilesAutoCompleteConfiguration: MultipleAutoCompleteConfiguration;

	constructor(
		private datasetWizardService: DatasetWizardService,
		private route: ActivatedRoute,
		public snackBar: MatSnackBar,
		public router: Router,
		private language: TranslateService,
		private configurationService: ConfigurationService,
		private externalSourcesService: ExternalSourcesService,
		private dialog: MatDialog,
		public dmpService: DmpService,
		public externalSourcesConfigurationService: ExternalSourcesConfigurationService,
		private uiNotificationService: UiNotificationService,
		private formService: FormService,
		private lockService: LockService,
		private location: Location,
		private authService: AuthService,
		private guidedTourService: GuidedTourService
	) {
		super();
	}

	ngOnInit() {

		if (this.formGroup.get('status').value === 1) {
			this.formGroup.disable();
		}

		this.datasetWizardModel = new DatasetWizardEditorModel();

		this.profilesAutoCompleteConfiguration = {
			filterFn: this.filterProfiles.bind(this),
			initialItems: (excludedItems: any[]) => this.filterProfiles('').pipe(map(result => result.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1))),
			displayFn: (item) => item['label'],
			titleFn: (item) => item['label'],
			subtitleFn: (item) => item['description'],
			popupItemActionIcon: 'visibility'
		};
	}

	public dashboardTourDmp: GuidedTour = {
		tourId: 'only-dmp-tour',
		useOrb: true,
		steps: [
			{
				title: this.dmpText,
				content: 'Step 1',
				orientation: Orientation.Bottom,
				highlightPadding: 3,
				isStepUnique: true,
				customTopOffset: 8
			}
		]
	};

	getDmpText(): string {
		return this.language.instant('DMP-LISTING.TEXT-INFO') + '\n\n' +
			this.language.instant('DMP-LISTING.TEXT-INFO-QUESTION') + ' ' +
			this.language.instant('DMP-LISTING.LINK-ZENODO') + ' ' +
			this.language.instant('DMP-LISTING.GET-IDEA');
	}

	setDashboardTourDmp(label: string): void {
		this.dashboardTourDmp.steps[0].title = this.getDmpText();
		this.dashboardTourDmp.steps[0].selector = '.dmp-tour-' + label;
	}

	public restartTour(label: string): void {
		this.setDashboardTourDmp(label);
		this.guidedTourService.startTour(this.dashboardTourDmp);

	}

	registerFormListeners() {
		// this.formGroup.get('dmp').valueChanges
		// 	.pipe(takeUntil(this._destroyed))
		// 	.subscribe(x => {
		// 		this.dmpValueChanged(x);
		// 	});

		// if (this.isNewDataset) {
			// this.formGroup.get('profile').valueChanges
			// 	.pipe(takeUntil(this._destroyed))
			// 	.subscribe(x => {
			// 		if (!isNullOrUndefined(x)) {
			// 			this.datasetProfileValueChanged(x.id);
			// 		}
			// 	});
		// }
	}

	dmpValueChanged(dmp: DmpListingModel) {
		if (dmp) {
			this.formGroup.get('profile').enable();
			this.loadDatasetProfiles();
		}
		else {
			this.availableProfiles = [];
			this.formGroup.get('profile').reset();
			this.formGroup.get('profile').disable();
			this.formGroup.removeControl('datasetProfileDefinition');
		}
	}

	datasetProfileValueChanged(profileId: string) {
		if (profileId && profileId.length > 0) {
			this.formGroup.removeControl('datasetProfileDefinition');
			this.getDefinition(profileId);
		}
	}

	onChanges(): void {
		this.formGroup.valueChanges
			.pipe(takeUntil(this._destroyed))
			.subscribe(val => {
				// this.formChanged.emit(val);
			});
	}

	onFormChanged(event) {
		// this.formChanged.emit(event);
	}

	getDefinition(profileId: string) {
		// if (this.formGroup.invalid) { setTimeout(() => this.stepper.selectedIndex = 0); return; }
		this.datasetWizardService.getDefinition(profileId)
			.pipe(takeUntil(this._destroyed))
			.subscribe(item => {
				this.datasetWizardModel.datasetProfileDefinition = new DatasetDescriptionFormEditorModel().fromModel(item);
				this.datasetProfileDefinitionModel = this.datasetWizardModel.datasetProfileDefinition;
				this.formGroup.addControl('datasetProfileDefinition', this.datasetProfileDefinitionModel.buildForm());
			});
	}

	loadDatasetProfiles() {
		const datasetProfileRequestItem: RequestItem<DatasetProfileCriteria> = new RequestItem();
		datasetProfileRequestItem.criteria = new DatasetProfileCriteria();
		datasetProfileRequestItem.criteria.id = this.dmpId;
		if (datasetProfileRequestItem.criteria.id) {
			this.datasetWizardService.getAvailableProfiles(datasetProfileRequestItem)
				.pipe(takeUntil(this._destroyed))
				.subscribe(items => {
					this.availableProfiles = items;
				});
		}
	}

	needsUpdate() {
		if (this.datasetWizardModel.isProfileLatestVersion || (this.datasetWizardModel.status === DatasetStatus.Finalized)
			|| (this.datasetWizardModel.isProfileLatestVersion == undefined && this.datasetWizardModel.status == undefined)) {
			return false;
		}
		else {
			return true;
		}
	}

	private pumpLock() {
		this.lock.touchedAt = new Date();
		this.lockService.createOrUpdate(this.lock).pipe(takeUntil(this._destroyed)).subscribe(async result => {
			if (!isNullOrUndefined(result)) {
				this.lock.id = Guid.parse(result);
			} else {
				this.location.back();
			}
		});
	}

	removeTag(tag: any) {
		(<FormArray>this.formGroup.get('tags')).removeAt(((<FormArray>this.formGroup.get('tags')).value as any[]).indexOf(tag));
	}

	addTag(ev: MatChipInputEvent) {
		if (ev.value !== '' && isNullOrUndefined(((<FormArray>this.formGroup.get('tags')).value as ExternalTagEditorModel[]).find(tag => tag.name === ev.value))) {
			(<FormArray>this.formGroup.get('tags')).push(new ExternalTagEditorModel('', ev.value).buildForm());
		}
		ev.input.value = '';
	}

	getProfileId(): string {
		if (!isNullOrUndefined(this.formGroup.get('profile').value)) {
			return this.formGroup.get('profile').value.id;
		} else {
			return undefined;
		}
	}

	hasProfileId(): boolean {
		return !isNullOrUndefined(this.getProfileId());
	}

	filterProfiles(value: string): Observable<DatasetProfileModel[]> {
		const request = new DataTableRequest<DatasetProfileCriteria>(null, null, { fields: ['+label'] });
		const criteria = new DatasetProfileCriteria();
		criteria.like = value;
		request.criteria = criteria;
		return this.dmpService.searchDMPProfiles(request);
	}

	allAvailableProfiles(event: MouseEvent) {
		event.stopPropagation();
		const dialogRef = this.dialog.open(AvailableProfilesComponent, {
			data: {
				profiles: this.formGroup.get('profiles')
			}
		});
		return false;
	}

	public compareWith(object1: any, object2: any) {
		return object1 && object2 && object1.id === object2.id;
	}
}
