import { CdkDrag, CdkDragDrop, CdkDropList, moveItemInArray } from '@angular/cdk/drag-drop';
import { DOCUMENT } from '@angular/common';
import { Component, EventEmitter, Inject, Input, OnInit, Output, SimpleChanges, ViewChild } from '@angular/core';
import { AbstractControl, FormArray, FormControl, FormGroup } from '@angular/forms';
import { BaseComponent } from '@common/base/base.component';
import { NewEntryType, ToCEntry, ToCEntryType } from '../table-of-contents-entry';

@Component({
	selector: 'app-dataset-profile-table-of-contents-internal-section',
	styleUrls: ['./table-of-contents-internal-section.scss'],
	templateUrl: './table-of-contents-internal-section.html'
})
export class DatasetProfileTableOfContentsInternalSection extends BaseComponent implements OnInit {

	@Input() links: ToCEntry[];
	@Output() itemClick = new EventEmitter<ToCEntry>();
	@Output() removeEntry = new EventEmitter<ToCEntry>();

	@Output() createFooEntry = new EventEmitter<NewEntryType>();

	@Output() dataNeedsRefresh = new EventEmitter<void>();



	@Input() parentLink: ToCEntry;
	@Input() itemSelected: ToCEntry;
	@Input() DRAGULA_ITEM_ID_PREFIX;
	@Input() overContainerId: string;
	@Input() isDragging;
	@Input() draggingItemId: string;
	@Input() parentRootId: string;

	@Input() colorizeInvalid:boolean = false;

	@Input() viewOnly: boolean;
	// @Input() dropListGroup: Set<string> = new Set<string>();
	// @Input() dropListGroup: string[];

	// @Input() dragHoveringOver: boolean = false;
	// @Input() depth: number = 0;

	// @Input() dropListStruct: { id: string, depth: number}[] = [];

	constructor(
		@Inject(DOCUMENT) private _document: Document) {
		super();
	}

	tocEntryType = ToCEntryType;


	// compareFn(a, b){
	// 	if(a.depth> b.depth) return -1;
	// 	if(a.depth< b.depth) return 1;

	// 	return 0;
	// }

	ngOnInit(): void {
	}

	// hoveroverEnter(){
	// 	// console.log('user hovering drag over', this.parentLink.id, this.parentLink.label);
	// 	this.dragHoveringOver = true;
	// }
	// hoveroverLeft(){
	// 	this.dragHoveringOver = false;
	// }

	ngOnChanges(changes: SimpleChanges) {

	}

	// get grouListIds(){
	// 	return Array.from(this.dropListGroup);
	// }
	itemClicked(item: ToCEntry) {
		//leaf node
		this.itemClick.emit(item);
	}

	deleteEntry(currentLink: ToCEntry){
		this.removeEntry.emit(currentLink);
	}

	createNewEntry(foo: NewEntryType){
		this.createFooEntry.emit(foo);
	}

	// tocEntryIsChildOf(testingChild: ToCEntry,parent: ToCEntry): boolean{

	// 	if(!testingChild || !parent) return false;

	// 	if(testingChild.id == parent.id){return true;}

	// 	if(parent.subEntries){
	// 		let childFound:boolean = false;

	// 		parent.subEntries.forEach(subEntry=>{
	// 			if(this.tocEntryIsChildOf(testingChild, subEntry)){
	// 				childFound = true;
	// 				return true;
	// 			}
	// 		})

	// 		return childFound;
	// 	}
	// 	return false;
	// }

	get selectedItemInLinks(){
		if(!this.links || !this.itemSelected) return false;

		const link = this.links.find(l=>l.id === this.itemSelected.id);

		if(link) return true;
		return false;
	}

	// appendAndGetDroplists(dropList: CdkDropList){
	// 	this.dropListGroup.push(dropList);
	// 	return this.dropListGroup;
	// }

	// drop(event: CdkDragDrop<string[]>) {
	// 	// if(!this.links || !this.links.length) return;

	// 	if(event.container === event.previousContainer){
	// 		moveItemInArray(this.links, event.previousIndex, event.currentIndex);
	
	// 		let arrayToUpdate: FormArray = this.links[0].form.parent as FormArray;
	// 		// if(this.parentLink && this.parentLink.form){
	// 		// 	switch(this.parentLink.subEntriesType){
	// 		// 		case this.tocEntryType.Field: 
	// 		// 			arrayToUpdate = (this.parentLink.form.get('fields') as FormArray);
	// 		// 			break;
	// 		// 		case this.tocEntryType.FieldSet: 
	// 		// 			arrayToUpdate = (this.parentLink.form.get('fieldSets') as FormArray);
	// 		// 			break;
	// 		// 		case this.tocEntryType.Section: 
	// 		// 			arrayToUpdate = (this.parentLink.form.get('sections') as FormArray);
	// 		// 			break
	// 		// 	}
				
	// 		// }
	// 		if(arrayToUpdate.controls){
	// 			moveItemInArray(arrayToUpdate.controls, event.previousIndex, event.currentIndex);
	// 			//update ordinality
	// 			arrayToUpdate.controls.forEach((element,idx ) => {
	// 				element.get('ordinal').setValue(idx);
	// 				element.updateValueAndValidity();
	// 			});
	// 		}
	
	// 		this.dataNeedsRefresh.emit();
	// 	}else{
	// 		console.log('not same container');
	// 	}

	// 	console.log(event.container.id);

	// }

	onDataNeedsRefresh(){
		this.dataNeedsRefresh.emit();
	}


	// get hoveringOverParent(){
	// 	if(!this.overContainerId) return false;
	// 	const child = this._findTocEntryById(this.overContainerId, this.parentLink.subEntries);
	// 	if(!child) return false;
	// 	return true;
	// }


	public _findTocEntryById(id: string, tocentries: ToCEntry[]): ToCEntry{
		if(!tocentries){
			return null;
		}

		let tocEntryFound = tocentries.find(entry=>entry.id === id);

		if(tocEntryFound){
			return tocEntryFound;
		}	

		for(let entry of tocentries){
			const result = this._findTocEntryById(id, entry.subEntries);
			if(result){
				tocEntryFound = result;
				break;
			}
		}
		
		return tocEntryFound? tocEntryFound: null;
	}



	colorError():boolean{

		if(!this.colorizeInvalid) return false;
		
		const form = this.parentLink.form;
		if((!form || form.valid || !form.touched) && this.parentLink.type !== this.tocEntryType.Page) return false;

		const allFieldsAreTouched = this.allFieldsAreTouched(form);

		//fieldset may have errros that are inside its controls and not in the fieldsetFormGroup
		if(this.parentLink.type === this.tocEntryType.FieldSet && allFieldsAreTouched) return true;

		if(form.errors && allFieldsAreTouched) return true;

		//check if page has sections
		if(this.parentLink.type === this.tocEntryType.Page && allFieldsAreTouched){
			const rootForm = form.root;
			if(rootForm){
				const sections = rootForm.get('sections') as FormArray;
				if(!sections.controls.find(section=>section.get('page').value === this.parentLink.id)){
					return true;
				}
			}
		}

	
		//checking first child form controls if have errors
		let hasErrors = false;
		if(allFieldsAreTouched){
			if(form instanceof FormGroup){
				const formGroup = form as FormGroup;
	
				const controls = Object.keys(formGroup.controls);
	
				controls.forEach(control=>{
					if(formGroup.get(control).errors){
						hasErrors = true;
					}
				})
	
			}
		}

		return hasErrors;
	}


	allFieldsAreTouched(aControl:AbstractControl){//auto na testaroume

		if(!aControl|| aControl.untouched) return false;

		if(aControl instanceof FormControl){
			return aControl.touched;
		}else if(aControl instanceof FormGroup){
			const controlKeys = Object.keys((aControl as FormGroup).controls);
			let areAllTouched = true;
			controlKeys.forEach(key=>{
				if(!this.allFieldsAreTouched(aControl.get(key))){
					areAllTouched = false;
				}
			})
			// const areAllTouched = controlKeys.reduce((acc, key)=>acc && this._allFieldsAreTouched(aControl.get(key)), true);
			return areAllTouched;

		}else if(aControl instanceof FormArray){
			const controls = (aControl as FormArray).controls;
			// const areAllTouched = controls.reduce((acc, control)=>acc && this._allFieldsAreTouched(control), true);
			let areAllTouched = true;
			// controls.reduce((acc, control)=>acc && this._allFieldsAreTouched(control), true);
			controls.forEach(control=>{
				if(!this.allFieldsAreTouched(control)){
					areAllTouched = false;
				}
			});
			return areAllTouched;
		}


		return false;
	}
}