import { FormBuilder, FormGroup, Validators } from "@angular/forms";
import { ExternalDatasetType } from '@app/core/common/enum/external-dataset-type';
import { DataRepositoryModel } from '@app/core/model/data-repository/data-repository';
import { DatasetProfileModel } from '@app/core/model/dataset/dataset-profile';
import { DatasetWizardModel } from '@app/core/model/dataset/dataset-wizard';
import { DmpModel } from '@app/core/model/dmp/dmp';
import { ExternalDatasetModel } from '@app/core/model/external-dataset/external-dataset';
import { RegistryModel } from '@app/core/model/registry/registry';
import { ServiceModel } from '@app/core/model/service/service';
import { TagModel } from '@app/core/model/tag/tag';
import { DatasetDescriptionFormEditorModel } from '@app/ui/misc/dataset-description-form/dataset-description-form.model';
import { BackendErrorValidator } from '@common/forms/validation/custom-validator';
import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model';
import { ValidationContext } from '@common/forms/validation/validation-context';

export class DatasetWizardEditorModel {
	public id: string;
	public label: string;
	public profile: DatasetProfileModel;
	public uri: String;
	public status: number;
	public description: String;
	public services: ExternalServiceEditorModel[] = [];
	public registries: ExternalRegistryEditorModel[] = [];
	public dataRepositories: ExternalDataRepositoryEditorModel[] = [];
	public tags: ExternalTagEditorModel[] = [];
	public externalDatasets: ExternalDatasetEditorModel[] = [];
	public dmp: DmpModel;
	public datasetProfileDefinition: DatasetDescriptionFormEditorModel;
	public validationErrorModel: ValidationErrorModel = new ValidationErrorModel();
	public isProfileLatestVersion: Boolean;
	public modified: Date;

	fromModel(item: DatasetWizardModel): DatasetWizardEditorModel {
		this.id = item.id;
		this.label = item.label;
		this.profile = item.profile;
		this.uri = item.uri;
		this.status = item.status;
		this.description = item.description;
		if (item.services) { this.services = item.services.map(x => new ExternalServiceEditorModel().fromModel(x)); }
		if (item.registries) { this.registries = item.registries.map(x => new ExternalRegistryEditorModel().fromModel(x)); }
		if (item.dataRepositories) { this.dataRepositories = item.dataRepositories.map(x => new ExternalDataRepositoryEditorModel().fromModel(x)); }
		if (item.externalDatasets) { this.externalDatasets = item.externalDatasets.map(x => new ExternalDatasetEditorModel().fromModel(x)); }
		this.dmp = item.dmp;
		if (item.datasetProfileDefinition) { this.datasetProfileDefinition = new DatasetDescriptionFormEditorModel().fromModel(item.datasetProfileDefinition); }
		if (item.tags) { this.tags = item.tags.map(x => new ExternalTagEditorModel().fromModel(x)); }
		this.isProfileLatestVersion = item.isProfileLatestVersion;
		this.modified = new Date(item.modified);
		return this;
	}

	buildForm(context: ValidationContext = null, disabled: boolean = false): FormGroup {
		if (context == null) { context = this.createValidationContext(); }
		const formBuilder = new FormBuilder();
		const formGroup = formBuilder.group({
			id: [{ value: this.id, disabled: disabled }, context.getValidation('id').validators],
			label: [{ value: this.label, disabled: disabled }, context.getValidation('label').validators],
			uri: [{ value: this.uri, disabled: disabled }, context.getValidation('uri').validators],
			status: [{ value: this.status, disabled: disabled }, context.getValidation('status').validators],
			description: [{ value: this.description, disabled: disabled }, context.getValidation('description').validators],
			dmp: [{ value: this.dmp, disabled: disabled }, context.getValidation('dmp').validators],
			//externalDatasets: [{ value: this.externalDatasets, disabled: disabled }, context.getValidation('externalDatasets').validators],
			tags: [{ value: this.tags, disabled: disabled }, context.getValidation('tags').validators],
			//registries: [{ value: this.registries, disabled: disabled }, context.getValidation('registries').validators],
			//dataRepositories: [{ value: this.dataRepositories, disabled: disabled }, context.getValidation('dataRepositories').validators],
			//services: [{ value: this.services, disabled: disabled }, context.getValidation('services').validators],
			profile: [{ value: this.profile, disabled: disabled }, context.getValidation('profile').validators],
			modified: [{value: this.modified, disabled: disabled}, context.getValidation('modified').validators]
		});

		const externalDatasetsFormArray = new Array<FormGroup>();
		//if (this.externalDatasets && this.externalDatasets.length > 0) {
		this.externalDatasets.forEach(item => {
			externalDatasetsFormArray.push(item.buildForm(context.getValidation('externalDatasets').descendantValidations, disabled));
		});
		// } else {
		// 	//externalDatasetsFormArray.push(new ExternalDatasetModel().buildForm(context.getValidation('externalDatasets').descendantValidations, disabled));
		// }
		formGroup.addControl('externalDatasets', formBuilder.array(externalDatasetsFormArray));

		// const tagsFormArray = new Array<FormGroup>();
		// if (this.tags && this.tags.length > 0) {
		// 	this.tags.forEach(item => {
		// 		tagsFormArray.push(item.buildForm(context.getValidation('tags').descendantValidations, disabled));
		// 	});
		// } else {
		// 	//externalDatasetsFormArray.push(new ExternalDatasetModel().buildForm(context.getValidation('externalDatasets').descendantValidations, disabled));
		// }
		// formGroup.addControl('tags', formBuilder.array(tagsFormArray));

		const registriesFormArray = new Array<FormGroup>();
		//if (this.registries && this.registries.length > 0) {
		this.registries.forEach(item => {
			registriesFormArray.push(item.buildForm(context.getValidation('registries').descendantValidations, disabled));
		});
		// } else {
		// 	//externalDatasetsFormArray.push(new ExternalDatasetModel().buildForm(context.getValidation('externalDatasets').descendantValidations, disabled));
		// }
		formGroup.addControl('registries', formBuilder.array(registriesFormArray));

		const dataRepositoriesFormArray = new Array<FormGroup>();
		//if (this.dataRepositories && this.dataRepositories.length > 0) {
		this.dataRepositories.forEach(item => {
			dataRepositoriesFormArray.push(item.buildForm(context.getValidation('dataRepositories').descendantValidations, disabled));
		});
		// } else {
		// 	//externalDatasetsFormArray.push(new ExternalDatasetModel().buildForm(context.getValidation('externalDatasets').descendantValidations, disabled));
		// }
		formGroup.addControl('dataRepositories', formBuilder.array(dataRepositoriesFormArray));

		const servicesFormArray = new Array<FormGroup>();
		// if (this.services && this.services.length > 0) {
		this.services.forEach(item => {
			servicesFormArray.push(item.buildForm(context.getValidation('services').descendantValidations, disabled));
		});
		// } else {
		// 	//externalDatasetsFormArray.push(new ExternalDatasetModel().buildForm(context.getValidation('externalDatasets').descendantValidations, disabled));
		// }
		formGroup.addControl('services', formBuilder.array(servicesFormArray));

		// const tagsFormArray = new Array<FormGroup>();
		// this.tags.forEach(item => {
		// 	tagsFormArray.push(item.buildForm(context.getValidation('tags').descendantValidations, disabled));
		// });
		// formGroup.addControl('tags', formBuilder.array(tagsFormArray));

		if (this.datasetProfileDefinition) { formGroup.addControl('datasetProfileDefinition', this.datasetProfileDefinition.buildForm()); }
		// formGroup.addControl('profile', this.profile.buildForm());
		return formGroup;
	}

	createValidationContext(): ValidationContext {
		const baseContext: ValidationContext = new ValidationContext();
		baseContext.validation.push({ key: 'id', validators: [BackendErrorValidator(this.validationErrorModel, 'id')] });
		baseContext.validation.push({ key: 'label', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'label')] });
		baseContext.validation.push({ key: 'profile', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'profile')] });
		baseContext.validation.push({ key: 'uri', validators: [BackendErrorValidator(this.validationErrorModel, 'uri')] });
		baseContext.validation.push({ key: 'status', validators: [BackendErrorValidator(this.validationErrorModel, 'status')] });
		baseContext.validation.push({ key: 'description', validators: [BackendErrorValidator(this.validationErrorModel, 'description')] });
		baseContext.validation.push({ key: 'services', validators: [BackendErrorValidator(this.validationErrorModel, 'services')] });
		baseContext.validation.push({ key: 'registries', validators: [BackendErrorValidator(this.validationErrorModel, 'registries')] });
		baseContext.validation.push({ key: 'dataRepositories', validators: [BackendErrorValidator(this.validationErrorModel, 'dataRepositories')] });
		baseContext.validation.push({ key: 'externalDatasets', validators: [BackendErrorValidator(this.validationErrorModel, 'externalDatasets')] });
		baseContext.validation.push({ key: 'dmp', validators: [BackendErrorValidator(this.validationErrorModel, 'dmp')] });
		baseContext.validation.push({ key: 'datasetProfileDefinition', validators: [BackendErrorValidator(this.validationErrorModel, 'datasetProfileDefinition')] });
		baseContext.validation.push({ key: 'tags', validators: [BackendErrorValidator(this.validationErrorModel, 'datasetProfileDefinition')] });
		baseContext.validation.push({ key: 'modified', validators: []});
		return baseContext;
	}
}

export class ExternalTagEditorModel {
	public abbreviation: String;
	public definition: String;
	public id: String;
	public name: String;
	public reference: String;
	public uri: String;

	constructor(id?: String, name?: String) {
		this.id = id;
		this.name = name;
	}

	fromModel(item: TagModel): ExternalTagEditorModel {
		this.id = item.id;
		this.name = item.name;
		return this;
	}

	buildForm(context: ValidationContext = null, disabled: boolean = false): FormGroup {
		return new FormBuilder().group({
			id: [this.id],
			name: [this.name]
		});
	}
}

export class ExternalServiceEditorModel {
	public id: String;
	public abbreviation: String;
	public definition: String;
	public uri: String;
	public label: String;
	public reference: String;
	public source: String;

	constructor(abbreviation?: String, definition?: String, id?: String, label?: String, reference?: String, uri?: String, source?: String) {
		this.id = id;
		this.abbreviation = abbreviation;
		this.definition = definition;
		this.uri = uri;
		this.label = label;
		this.reference = reference;
		this.source = source;
	}

	fromModel(item: ServiceModel): ExternalServiceEditorModel {
		this.id = item.id;
		this.abbreviation = item.abbreviation;
		this.definition = item.definition;
		this.uri = item.uri;
		this.label = item.label;
		this.reference = item.reference;
		this.source = item.source;
		return this;
	}

	buildForm(context: ValidationContext = null, disabled: boolean = false): FormGroup {
		return new FormBuilder().group({
			id: [this.id],
			abbreviation: [this.abbreviation],
			label: [this.label, Validators.required],
			reference: [this.reference],
			uri: [this.uri, Validators.required],
			definition: [this.definition],
			source: [this.source]
		});
	}
}

export class ExternalRegistryEditorModel {
	public abbreviation: String;
	public definition: String;
	public id: String;
	public label: String;
	public reference: String;
	public uri: String;
	public source: String

	constructor(abbreviation?: String, definition?: String, id?: String, label?: String, reference?: String, uri?: String, source?: String) {
		this.abbreviation = abbreviation;
		this.definition = definition;
		this.id = id;
		this.label = label;
		this.reference = reference;
		this.uri = uri;
		this.source = source;
	}

	fromModel(item: RegistryModel): ExternalRegistryEditorModel {
		this.abbreviation = item.abbreviation;
		this.definition = item.definition;
		this.id = item.id;
		this.label = item.label;
		this.reference = item.pid ? item.pid : item.reference;
		this.uri = item.uri;
		this.source = item.source

		return this;
	}

	buildForm(context: ValidationContext = null, disabled: boolean = false): FormGroup {
		return new FormBuilder().group({
			id: [this.id],
			abbreviation: [this.abbreviation],
			label: [this.label, Validators.required],
			reference: [this.reference],
			uri: [this.uri, Validators.required],
			definition: [this.definition],
			source: [this.source]
		});
	}
}

export class ExternalDatasetEditorModel {

	public abbreviation: String;
	public id: String;
	public name: String;
	public reference: String;
	public type: ExternalDatasetType;
	public info: String;
	public validationErrorModel: ValidationErrorModel = new ValidationErrorModel();
	public source: String;

	constructor(id?: string, abbreviation?: string, name?: string, reference?: string, source?: String, info?: string, type?: ExternalDatasetType) {
		this.id = id;
		this.name = name;
		this.abbreviation = abbreviation;
		this.reference = reference;
		this.info = info;
		this.type = type;
		this.source = source;
	}

	fromModel(item: ExternalDatasetModel): ExternalDatasetEditorModel {
		this.abbreviation = item.abbreviation;
		this.id = item.id;
		this.name = item.name;
		this.reference = item.reference;
		this.type = item.type;
		this.info = item.info;
		this.source = item.source;
		return this;
	}

	buildForm(context: ValidationContext = null, disabled: boolean = false): FormGroup {
		return new FormBuilder().group({
			id: [this.id],
			abbreviation: [this.abbreviation],
			name: [this.name, Validators.required],
			reference: [this.reference],
			type: [this.type],
			info: [this.info],
			source: [this.source]
		});
	}
}

export class ExternalDataRepositoryEditorModel {
	public id: string;
	public name: string;
	public abbreviation: string;
	public uri: string;
	public reference: string;
	public info: string;
	public created: Date;
	public modified: Date;
	public source: string;

	constructor(id?: string, name?: string, abbreviation?: string, uri?: string, reference?: string, source?: string) {
		this.id = id;
		this.name = name;
		this.abbreviation = abbreviation;
		this.uri = uri;
		this.reference = reference;
		this.source = source;
	}

	fromModel(item: DataRepositoryModel): ExternalDataRepositoryEditorModel {
		this.id = item.id;
		this.name = item.name;
		this.abbreviation = item.abbreviation;
		this.uri = item.uri;
		this.info = item.info;
		this.reference = item.pid;
		this.source = item.source;
		return this;
	}

	buildForm(context: ValidationContext = null, disabled: boolean = false): FormGroup {
		return new FormBuilder().group({
			id: [this.id],
			name: [this.name, [Validators.required]],
			abbreviation: [this.abbreviation],
			uri: [this.uri, [Validators.required]],
			info: [this.info],
			reference: [this.reference],
			source: [this.source]
		});
	}
}

// export class TagModel implements Serializable<TagModel> {

// 	public id: string;
// 	public name: string;

// 	constructor(id?: string, name?: string) {
// 		this.id = id;
// 		this.name = name;
// 	}

// 	fromJSONObject(item: any): TagModel {
// 		this.id = item.id;
// 		this.name = item.name;
// 		return this;
// 	}

// 	buildForm(context: ValidationContext = null, disabled: boolean = false): FormGroup {
// 		return new FormBuilder().group({
// 			id: [this.id],
// 			name: [this.name]
// 		});
// 	}
// }
