import { BaseComponent } from '@common/base/base.component';
import { OnInit, Component, Input, EventEmitter, Output, ViewChild } from '@angular/core';
import { AbstractControl, FormGroup, Validators } from '@angular/forms';
import { TranslateService } from '@ngx-translate/core';
import { GrantTabModel } from '../grant-tab/grant-tab-model';
import { SingleAutoCompleteConfiguration } from '@app/library/auto-complete/single/single-auto-complete-configuration';
import { FunderService } from '@app/core/services/funder/funder.service';
import { ProjectService } from '@app/core/services/project/project.service';
import { GrantService } from '@app/core/services/grant/grant.service';
import { RequestItem } from '@app/core/query/request-item';
import { GrantCriteria } from '@app/core/query/grant/grant-criteria';
import { ProjectCriteria } from '@app/core/query/project/project-criteria';
import { FunderCriteria } from '@app/core/query/funder/funder-criteria';
import { debounceTime, filter, map, switchMap, takeUntil, tap } from 'rxjs/operators';

import { isNullOrUndefined } from '@swimlane/ngx-datatable';
@Component({
	selector: 'funding-info',
	templateUrl: './funding-info.component.html',
	styleUrls: ['./funding-info.component.scss']
})
export class FundingInfoComponent extends BaseComponent implements OnInit {

	// @Input() formGroup: FormGroup = null;
	@Input() isUserOwner: boolean;
	@Input() isNew: boolean;
	@Input() isFinalized: boolean;
	@Input() isClone: boolean = false;
	@Input() isNewVersion: boolean;

	@Input() formGroup: FormGroup;
	@Input() grantformGroup: FormGroup;
	@Input() projectFormGroup: FormGroup;
	@Input() funderFormGroup: FormGroup = null;
	@Output() onFormChanged: EventEmitter<any> = new EventEmitter();

	isCreateNew = false;
	isCreateNewProject = false;
	isCreateNewFunder = false;
	grant: GrantTabModel;
	// forceFocus = false;

	grantAutoCompleteConfiguration: SingleAutoCompleteConfiguration;
	projectAutoCompleteConfiguration: SingleAutoCompleteConfiguration;
	funderAutoCompleteConfiguration: SingleAutoCompleteConfiguration;

	isFunderPending:boolean = false;
	isGrantPending:boolean = false;
	isProjectPending:boolean = false;

	private readonly _FUNDER_PREFIX = "dmp:";
	private readonly _GRANT_PREFIX = "dmp:";
	private readonly _PROJECT_PREFIX = "dmp:";
	private readonly _KEY = "Internal";


	constructor(
		private grantService: GrantService,
		private projectService: ProjectService,
		private funderService: FunderService,
		private language: TranslateService
	) {
		super();
	}

	getGrantIdText(item) {
		if (item.reference != null && typeof item.reference == 'string') {
			const parts = (item.reference as String).split('::');
			return parts.length > 1 ? ' (' + parts[parts.length - 1] + ')' : '';
		}
		return '';
	}

	ngOnInit() {
		const grantRequestItem: RequestItem<GrantCriteria> = new RequestItem();
		grantRequestItem.criteria = new GrantCriteria();

		this.configureAutoCompletes();

		this.initializeReferenceValidators();

		this.isCreateNew = (this.grantformGroup.get('label').value != null && this.grantformGroup.get('label').value.length > 0);
		this.isCreateNewProject = (this.projectFormGroup.get('label').value != null && this.projectFormGroup.get('label').value.length > 0);
		this.isCreateNewFunder = (this.funderFormGroup.get('label').value != null && this.funderFormGroup.get('label').value.length > 0);
		this.setGrantValidators();
		this.setProjectValidators();
		this.setFunderValidators();
		this.registerFormListeners();
		if (this.isNew && !this.isClone) {
			this.grantformGroup.reset();
			this.grantformGroup.disable();
		}

		this.formGroup.valueChanges.pipe(takeUntil(this._destroyed))
			.subscribe(x => {
				this.configureAutoCompletes();
			});
	}
	initializeReferenceValidators() {

		//Validator for funder
		this.funderFormGroup.get('reference').valueChanges.pipe(
			takeUntil(this._destroyed),
			filter(value =>!isNullOrUndefined(value)),
			tap(_=>this.isFunderPending = true),
			debounceTime(500),
			switchMap(value=> {
				const requestItem = new RequestItem<FunderCriteria>();
				requestItem.criteria = new FunderCriteria();
				requestItem.criteria.exactReference = this._FUNDER_PREFIX +value;
				return this.funderService.getWithExternal(requestItem).pipe(takeUntil(this._destroyed));
			}),
			map(response=>{
				if(response && response.length){
					const internalFunders = (response as Array<any>).filter(funder=> funder.key === this._KEY);

					if(internalFunders && internalFunders.length){
						return {funderIdentifierExists:true};
					}
					return null;
				}
				return null;
			})
			)
		.subscribe(error=>{
			this.isFunderPending = false;
			this.funderFormGroup.get('reference').setErrors(error);
			if(!error && this.funderFormGroup.get('reference').validator){
				const validator = this.funderFormGroup.get('reference').validator({} as AbstractControl);
				if(validator && validator.required && this.funderFormGroup.get('reference').touched && !this.funderFormGroup.get('reference').value){
					this.funderFormGroup.get('reference').setErrors({required : true});
				}
			}
		});

		//Validator for grants
		this.grantformGroup.get('reference').valueChanges.pipe(
			takeUntil(this._destroyed),
			filter(value =>!isNullOrUndefined(value)),
			tap(_=> this.isGrantPending = true),
			debounceTime(500),
			switchMap(value=> {
				const requestItem = new RequestItem<GrantCriteria>();
				requestItem.criteria = new GrantCriteria();
				requestItem.criteria.exactReference = this._GRANT_PREFIX + value;
				return this.grantService.getWithExternal(requestItem).pipe(takeUntil(this._destroyed));
			}),
			map(response=>{
				if(response && response.length){
					const internalGrants = (response as Array<any>).filter(grant=> grant.key === this._KEY);

					if(internalGrants && internalGrants.length){
						return {grantIdentifierExists:true};
					}
					return null;
				}
				return null;
			})
			)
		.subscribe(error=>{
			this.isGrantPending = false;
			this.grantformGroup.get('reference').setErrors(error);
			if(!error && this.grantformGroup.get('reference').validator){
				const validator = this.grantformGroup.get('reference').validator({} as AbstractControl);
				if(validator && validator.required && this.grantformGroup.get('reference').touched && !this.grantformGroup.get('reference').value){
					this.grantformGroup.get('reference').setErrors({required : true});
				}
			}
		});

		//validator for projects
		this.projectFormGroup.get('reference').valueChanges.pipe(
			takeUntil(this._destroyed),
			filter(value =>!isNullOrUndefined(value)),
			tap(_ => this.isProjectPending = true),
			debounceTime(500),
			switchMap(value=> {
				const requestItem = new RequestItem<ProjectCriteria>();
				requestItem.criteria = new ProjectCriteria();
				requestItem.criteria.exactReference = this._PROJECT_PREFIX + value;
				return this.projectService.getWithExternal(requestItem).pipe(takeUntil(this._destroyed));
			}),
			map(response=>{
				if(response && response.length){
					const internalProjects = (response as Array<any>).filter(project=> project.key === this._KEY);
					if(internalProjects && internalProjects.length){
						return {projectIdentifierExists:true};
					}
					return null;
				}
				return null;
			})
			)
		.subscribe(error=>{
			this.isProjectPending = false;
			this.projectFormGroup.get('reference').setErrors(error);
			if(!error && this.projectFormGroup.get('reference').validator){
				const validator = this.projectFormGroup.get('reference').validator({} as AbstractControl);
				if(validator && validator.required && this.projectFormGroup.get('reference').touched && !this.projectFormGroup.get('reference').value){
					this.projectFormGroup.get('reference').setErrors({required : true});
				}
			}
		});
	}

	configureAutoCompletes(): void {
		this.funderAutoCompleteConfiguration = {
			filterFn: this.searchFunder.bind(this),
			initialItems: () => this.searchFunder(''),
			displayFn: (item) => item['label'],
			titleFn: (item) => item['label'],
			subtitleFn: (item) => item['source'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['source'] : (item['key'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['key'] : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE'))
		}

		this.grantAutoCompleteConfiguration = {
			filterFn: this.searchGrant.bind(this),
			initialItems: () => this.searchGrant(''),
			displayFn: (item) => item['label'] + this.getGrantIdText(item),
			titleFn: (item) => item['label'] + this.getGrantIdText(item),
			subtitleFn: (item) => item['source'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['source'] : (item['key'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['key'] : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE')),
		}
		// this.forceFocus = false;

		this.projectAutoCompleteConfiguration = {
			filterFn: this.searchProject.bind(this),
			initialItems: () => this.searchProject(''),
			displayFn: (item) => item['label'],
			titleFn: (item) => item['label'],
			subtitleFn: (item) => item['source'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['source'] : (item['key'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['key'] : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE'))
		}
	}

	searchGrant(query: any) {
		const grantRequestItem: RequestItem<GrantCriteria> = new RequestItem();
		grantRequestItem.criteria = new GrantCriteria();
		grantRequestItem.criteria.like = query;
		const existFunderValue = this.funderFormGroup.get('existFunder').value;
		if (existFunderValue && !this.isCreateNewFunder && (existFunderValue.key != this._KEY)) {
			grantRequestItem.criteria.funderReference = this.funderFormGroup.controls['existFunder'].value.reference;
		}
		return this.grantService.getWithExternal(grantRequestItem);
	}

	searchProject(query: string) {
		const projectRequestItem: RequestItem<ProjectCriteria> = new RequestItem();
		projectRequestItem.criteria = new ProjectCriteria();
		projectRequestItem.criteria.like = query;
		return this.projectService.getWithExternal(projectRequestItem);
	}

	searchFunder(query: string) {
		const funderRequestItem: RequestItem<FunderCriteria> = new RequestItem();
		funderRequestItem.criteria = new FunderCriteria();
		funderRequestItem.criteria.like = query;
		return this.funderService.getWithExternal(funderRequestItem)
	}

	createGrant() {
		if (this.isNewVersion) { return };
		if (this.isGrantDisabled()) return;
		this.isCreateNew = !this.isCreateNew;
		this.setGrantValidators();
	}

	createProject() {
		if (this.isNewVersion) { return };
		this.isCreateNewProject = !this.isCreateNewProject;
		this.setProjectValidators();
	}

	createFunder() {
		if (this.isNewVersion) { return };
		this.isCreateNewFunder = !this.isCreateNewFunder;
		this.setFunderValidators();
	}

	setGrantValidators() {
		if (this.isCreateNew) {
			this.grantformGroup.get('existGrant').disable();
			this.grantformGroup.get('label').enable();
			this.grantformGroup.get('description').enable();

			this.grantformGroup.get('reference').enable();
			this.grantformGroup.get('reference').setValidators(Validators.required);
			this.grantformGroup.get('reference').updateValueAndValidity();
		} else if (this.isClone && !this.isNewVersion) {
			this.grantformGroup.get('existGrant').enable();
			this.grantformGroup.get('label').disable();
			this.grantformGroup.get('label').reset();
			this.grantformGroup.get('description').disable();
			this.grantformGroup.get('description').reset();

			this.grantformGroup.get('reference').disable();
			this.grantformGroup.get('reference').clearValidators();
			this.grantformGroup.get('reference').setErrors(null);
			this.grantformGroup.get('reference').updateValueAndValidity();
		} else if (this.isFinalized || this.isNewVersion || !this.isUserOwner) {
			this.grantformGroup.get('existGrant').disable();
			this.grantformGroup.get('label').disable();
			this.grantformGroup.get('description').disable();

			this.grantformGroup.get('reference').disable();
			this.grantformGroup.get('reference').clearValidators();
			this.grantformGroup.get('reference').setErrors(null);
			this.grantformGroup.get('reference').updateValueAndValidity();
		} else {
			this.grantformGroup.get('existGrant').enable();
			this.grantformGroup.get('label').disable();
			this.grantformGroup.get('label').reset();
			this.grantformGroup.get('description').disable();
			this.grantformGroup.get('description').reset();

			this.grantformGroup.get('reference').disable();
			this.grantformGroup.get('reference').clearValidators();
			this.grantformGroup.get('reference').setErrors(null);
			this.grantformGroup.get('reference').updateValueAndValidity();
		}
	}

	setProjectValidators() {
		if (this.isCreateNewProject) {
			this.projectFormGroup.get('existProject').disable();
			this.projectFormGroup.get('label').enable();
			this.projectFormGroup.get('description').enable();

			this.projectFormGroup.get('reference').enable()
			this.projectFormGroup.get('reference').setValidators(Validators.required);
			this.projectFormGroup.get('reference').updateValueAndValidity();
		} else if (this.isClone && !this.isNewVersion) {
			this.projectFormGroup.get('existProject').enable();
			this.projectFormGroup.get('label').disable()
			this.projectFormGroup.get('label').reset();
			this.projectFormGroup.get('description').disable();
			this.projectFormGroup.get('description').reset();

			this.projectFormGroup.get('reference').disable();
			this.projectFormGroup.get('reference').clearValidators();
			this.projectFormGroup.get('reference').setErrors(null);
			this.projectFormGroup.get('reference').updateValueAndValidity();
		} else if (this.isFinalized || this.isNewVersion || !this.isUserOwner) {
			this.projectFormGroup.get('existProject').disable();
			this.projectFormGroup.get('label').disable();
			this.projectFormGroup.get('description').disable();

			this.projectFormGroup.get('reference').disable();
			this.projectFormGroup.get('reference').clearValidators();
			this.projectFormGroup.get('reference').setErrors(null);
			this.projectFormGroup.get('reference').updateValueAndValidity();
		} else {
			this.projectFormGroup.get('existProject').enable();
			this.projectFormGroup.get('label').disable();
			this.projectFormGroup.get('label').reset();
			this.projectFormGroup.get('description').disable();
			this.projectFormGroup.get('description').reset();

			this.projectFormGroup.get('reference').disable();
			this.projectFormGroup.get('reference').clearValidators();
			this.projectFormGroup.get('reference').setErrors(null);
			this.projectFormGroup.get('reference').updateValueAndValidity();
		}
	}

	setFunderValidators() {
		if (this.isCreateNewFunder) {
			this.funderFormGroup.get('existFunder').disable();
			this.funderFormGroup.get('label').enable();

			this.funderFormGroup.get('reference').enable();
			this.funderFormGroup.get('reference').setValidators(Validators.required);
			this.funderFormGroup.get('reference').updateValueAndValidity();
			
		} else if (this.isClone && !this.isNewVersion) {
			if (this.funderFormGroup.get('existFunder')) {
				this.funderFormGroup.get('existFunder').enable();
				this.funderFormGroup.get('label').disable();
				this.funderFormGroup.get('label').reset();
				this.funderFormGroup.get('reference').disable();
				this.funderFormGroup.get('reference').clearValidators();
				this.funderFormGroup.get('reference').setErrors(null);
				this.funderFormGroup.get('reference').updateValueAndValidity();
			} else {
				this.funderFormGroup.get('label').enable();
				this.funderFormGroup.get('reference').enable();
				this.funderFormGroup.get('reference').setValidators(Validators.required);
				this.funderFormGroup.get('reference').updateValueAndValidity();
			}
		} else if (this.isFinalized || this.isNewVersion || !this.isUserOwner) {
			this.funderFormGroup.get('existFunder').disable();
			this.funderFormGroup.get('label').disable();

			this.funderFormGroup.get('reference').disable();
			this.funderFormGroup.get('reference').clearValidators();
			this.funderFormGroup.get('reference').setErrors(null);
			this.funderFormGroup.get('reference').updateValueAndValidity();
		} else {
			this.funderFormGroup.enable();
			this.funderFormGroup.get('label').disable();
			this.funderFormGroup.get('label').reset();

			this.funderFormGroup.get('reference').disable();
			this.funderFormGroup.get('reference').clearValidators();
			this.funderFormGroup.get('reference').setErrors(null);
			this.funderFormGroup.get('reference').updateValueAndValidity();
		}
	}

	registerFormListeners() {
		this.funderFormGroup.valueChanges
			.pipe(takeUntil(this._destroyed))
			.subscribe(x => {
				this.funderValueChanged(x);
			})
	}

	funderValueChanged(funder: any) {
		if ((funder.label !== "" && funder.label !== null && funder.label !== undefined && !isNullOrUndefined(funder.reference) && funder.reference.length )
			|| (funder.existFunder !== null && funder.existFunder !== undefined && funder.existFunder.id !== undefined)) {
			this.grantformGroup.reset();
			this.grantformGroup.enable();
			this.setGrantValidators();
		} else {
			this.grantformGroup.reset();
			this.grantformGroup.disable();
			if (this.isCreateNew) this.isCreateNew = !this.isCreateNew;
		}
	}

	isGrantDisabled() {
		return this.grantformGroup.disabled;
	}

	showToggleButton() {
		return (!this.isFinalized && this.isUserOwner) || this.isClone;
	}


	private consoleForm(){
		console.log(this.formGroup);
	}
}
