import { Component, Input, OnInit } from '@angular/core';
import { AbstractControl, FormArray, FormGroup } from '@angular/forms';
import { VisibilityRulesService } from '@app/ui/misc/dataset-description-form/visibility-rules/visibility-rules.service';
import { BaseComponent } from '@common/base/base.component';
import { takeUntil } from 'rxjs/operators';

@Component({
	selector: 'app-form-progress-indication',
	templateUrl: './form-progress-indication.component.html'
})
export class FormProgressIndicationComponent extends BaseComponent implements OnInit {
	@Input() formGroup: FormGroup;
	@Input() public progressValueAccuracy = 2;
	determinateProgressValue: number;

	constructor(private visibilityRulesService: VisibilityRulesService) { super(); }

	public value = 0;
	ngOnInit() {
		this.calculateValueForProgressbar();
		this.formGroup
			.valueChanges
			.pipe(takeUntil(this._destroyed))
			.subscribe(control => {
				this.calculateValueForProgressbar();
			});
	}

	calculateValueForProgressbar() {
		const progressSoFar = this.countFormControlsWithValueForProgress(this.formGroup);
		const total = this.CountFormControlDepthLengthFotTotal(this.formGroup);
		const perc = (progressSoFar / total) * 100;
		this.value = Number.parseFloat(perc.toPrecision(this.progressValueAccuracy));
	}

	countFormControlsWithValueForProgress(formControl: AbstractControl): number {
		let valueCurent = 0;
		if (formControl instanceof FormGroup) {
			if (this.checkFormsIfIsFieldsAndVisible(formControl)) {
				if (this.haseValue(formControl))
					valueCurent++;
			}
			if (this.chechFieldIfIsFieldSetAndVisible((formControl as FormGroup))) {
				valueCurent = valueCurent + this.compositeFieldsGetChildsForProgress(formControl);
			} else {
				Object.keys(formControl.controls).forEach(item => {
					const control = formControl.get(item);
					valueCurent = valueCurent + this.countFormControlsWithValueForProgress(control);
				});
			}
		} else if (formControl instanceof FormArray) {
			formControl.controls.forEach(item => {
				valueCurent = valueCurent + this.countFormControlsWithValueForProgress(item);
			});
		}
		return valueCurent;
	}
	private haseValue(formGroup: FormGroup): boolean {
		if (formGroup.get('value').value != null && formGroup.get('value').value !== '' && this.visibilityRulesService.checkElementVisibility(formGroup.get('id').value)) {
			return true;
		}
		return false;
	}

	private compositeFieldsGetChildsForProgress(formGroup: FormGroup): number {
		let valueCurent = 0;
		if (this.visibilityRulesService.checkElementVisibility(formGroup.get('id').value)) {
			(formGroup.get('fields') as FormArray).controls.forEach((element: FormGroup) => {
				valueCurent = valueCurent + this.countFormControlsWithValueForProgress(element);
			});

			(formGroup.get('multiplicityItems') as FormArray).controls.forEach((element: FormGroup) => {
				valueCurent = valueCurent + this.countFormControlsWithValueForProgress(element);
			});
		}
		return valueCurent;
	}



	private checkFormsIfIsFieldsAndVisible(formControl: FormGroup): boolean {
		if (formControl.contains('id') && formControl.contains('value')) {
			return true;
		}
		return false;
	}
	private chechFieldIfIsFieldSetAndVisible(formControl: FormGroup): boolean {
		if (formControl.contains('id') && formControl.contains('fields')) {
			return true;
		}
		return false;
	}

	CountFormControlDepthLengthFotTotal(formControl: AbstractControl): number {
		let valueCurent = 0;
		if (formControl instanceof FormArray) {
			formControl.controls.forEach(item => {
				valueCurent = valueCurent + this.CountFormControlDepthLengthFotTotal(item);
			});
		} else if (formControl instanceof FormGroup) {
			if ((formControl as FormGroup).contains('id') && (formControl as FormGroup).contains('value') && (this.visibilityRulesService.checkElementVisibility((formControl as FormGroup).get('id').value))) {
				valueCurent++;
			} else if ((formControl as FormGroup).contains('id') && (formControl as FormGroup).contains('fields')) {
				valueCurent = valueCurent + this.compositeFieldsGetChildsForTotal(formControl);
			} else {
				Object.keys(formControl.controls).forEach(item => {
					const control = formControl.get(item);
					valueCurent = valueCurent + this.CountFormControlDepthLengthFotTotal(control);
				});
			}
		}

		return valueCurent;
	}

	private compositeFieldsGetChildsForTotal(formGroup: FormGroup): number {
		let valueCurent = 0;
		if (this.visibilityRulesService.checkElementVisibility(formGroup.get('id').value)) {
			(formGroup.get('fields') as FormArray).controls.forEach((element: FormGroup) => {
				valueCurent = valueCurent + this.CountFormControlDepthLengthFotTotal(element);
			});
			(formGroup.get('multiplicityItems') as FormArray).controls.forEach((element: FormGroup) => {
				valueCurent = valueCurent + this.CountFormControlDepthLengthFotTotal(element);
			});
		}
		return valueCurent;
	}
}
