import { OnDestroy } from '@angular/core';
import { Component, ElementRef, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core';
import { FormArray, FormGroup } from '@angular/forms';
import { Guid } from '@common/types/guid';
import { isNullOrUndefined } from '@swimlane/ngx-datatable';
import { DragulaService } from 'ng2-dragula';
import { pipe, Subject, Subscription } from 'rxjs';
import { debounceTime, delay, tap } from 'rxjs/operators';
import { FieldEditorModel } from '../../../admin/field-editor-model';
import { FieldSetEditorModel } from '../../../admin/field-set-editor-model';
import { ToCEntry, ToCEntryType } from '../../../table-of-contents/table-of-contents-entry';
import { GENERAL_ANIMATIONS } from '../../animations/animations';

@Component({
	selector: 'app-dataset-profile-editor-section-fieldset-component',
	templateUrl: './dataset-profile-editor-section-fieldset.component.html',
	styleUrls: ['./dataset-profile-editor-section-fieldset.component.scss'],
	animations:[GENERAL_ANIMATIONS]
})

export class DatasetProfileEditorSectionFieldSetComponent implements OnInit, OnChanges, OnDestroy {
	// @Input() form: FormGroup;
	//@Input() dataModel: SectionEditorModel;
	// @Input() indexPath: string;
	@Input() viewOnly: boolean;
	// @Input() numbering: string;
	@Input() tocentry: ToCEntry;

	@Output() selectedEntryId = new EventEmitter<string>();
	@Output() dataNeedsRefresh = new EventEmitter<void> ();
	@Output() removeFieldSet = new EventEmitter<string>();
	@Output() addNewFieldSet = new EventEmitter<FormGroup>();
	@Output() cloneFieldSet = new EventEmitter<FormGroup>();


	// FIELDSET_PREFIX_ID="FIELDSET_PREFIX_ID";

	// @Output() fieldsetAdded = new EventEmitter<String>(); //returns the id of the fieldset added
	idprefix = "id";
	readonly dragula_prefix = "dragulaid";
	private subs = new Subscription();
	private FIELDSETS = 'FIELDSETS';

	private initializer = new Subject<void>();
	private scroller = new Subject<string>();
	// private $selectedFieldsetId = new Subject<string>();
	constructor(
		private dragulaService: DragulaService,
		private myElement: ElementRef
	)
	{
		if(this.dragulaService.find(this.FIELDSETS)){
			this.dragulaService.destroy(this.FIELDSETS);
		}


		this.dragulaService.createGroup(this.FIELDSETS,{
			moves:(el, container, handle)=>{
				// if(this.viewOnly) return false; //uncomment if want to unable drag n drop in viewonly mode
				if(el.id != (this.dragula_prefix+this.tocentry.id)) return false;
				if(handle.className && handle.classList.contains('handle')) return true;
				return false;
			}
		});
		this.subs.add(this.dragulaService.drop(this.FIELDSETS).subscribe(obs=>{


			(this.form.get('fieldSets') as FormArray).controls.forEach((e,i)=>{
				e.get('ordinal').setValue(i);
			});


			// obs.
			this.dataNeedsRefresh.emit();
			return ;
		}));
		const initializerSub = this.initializer
		.pipe(
			debounceTime(100)
		)
		.subscribe(() =>{
			this.initialize();
		});
		this.subs.add(initializerSub);
		this.subs.add(
			this.scroller
			.pipe(debounceTime(700))
			.subscribe(id => {
				if(isNullOrUndefined(id)){
					this._scrollOnTop();
					return ;
				}
				this._scrollToElement(id);
			})
		);

		// this.subs.add(
		// 	this.$selectedFieldsetId
		// 	.pipe(
		// 		debounceTime(100)
		// 	)
		// 	.subscribe(id => this.selectedEntryId.emit(id))
		// );

	}
	ngOnDestroy(){
		// console.log('elemement destroyed -->');

		this.subs.unsubscribe();
	}
	ngOnChanges(changes: SimpleChanges): void {
		this.initializer.next();
	}


	form;
	numbering;



	private _selectedFieldSetId: string = null;
	get selectedFieldSetId(){
		return this._selectedFieldSetId;
	}
	set selectedFieldSetId(id: string){

		if(id === this._selectedFieldSetId) return;
		this._selectedFieldSetId = id;
		this.selectedEntryId.emit(id);
	}





	// private _findParentSection():FormGroup{
	// 	const parent = this.form.parent;

	// 	return parent;
	// }


	private initialize(){
		if(this.tocentry.type === ToCEntryType.Section){
			this.form = this.tocentry.form;
			this.numbering = this.tocentry.numbering;
			this._selectedFieldSetId = null;

			// this.scroller.next(null);
			this._scrollOnTop(true);
		}else if(this.tocentry.type === ToCEntryType.FieldSet){
			this.form = this.tocentry.form.parent.parent;
			const numberingArray = this.tocentry.numbering.split('.');
			if(numberingArray.length){
				numberingArray.splice(numberingArray.length-1);
				this.numbering = numberingArray.join('.');
			}else{
				// console.warn('!not found numbering');
			}
			this._selectedFieldSetId = this.tocentry.id;

			// this._scrollToElement(this.selectedFieldSetId);
			this.scroller.next(this.tocentry.id);
		}else{//scroll on top
			// this._scrollOnTop();
			this.scroller.next(null);
		}
	}

	private _scrollToElement(id: string){
		let el = this.myElement.nativeElement.querySelector("#"+this.idprefix+id);
		if(el){
			el.scrollIntoView({behavior: "smooth", block:'start'});
		}
	}
	private _scrollOnTop(instant?: boolean){
		const el = this.myElement.nativeElement.querySelector('#topofcontainer');
		if(el){
			if(instant){
				el.scrollIntoView({ block:'end'});
			}else{
				el.scrollIntoView({behavior:'smooth', block:'end'});
			}
		}
	}
	ngOnInit() {

	}

	onRemoveFieldSet(fieldsetId: string){
		this.removeFieldSet.emit(fieldsetId);
	}

	onCloneFieldSet(fieldset: FormGroup){
		this.cloneFieldSet.emit(fieldset);
	}
	onAddFieldSet(){
		// this.addNewFieldSet.emit(this.form);
		try{
			const length = (this.form.get('fieldSets') as FormArray).length;
			if(length === 0){
				this.addFieldSetAfter(-9999, 0);
				return;
			}
			else{
				const lastElement = (this.form.get('fieldSets') as FormArray).at(length -1);
				this.addFieldSetAfter(lastElement.get('ordinal').value, length-1);
			}
		} catch {}
	}

	addFieldSetAfter(afterOrdinal: number, afterIndex: number):void{
		const field: FieldEditorModel = new FieldEditorModel();
		field.id = Guid.create().toString();
		field.ordinal = 0;//first filed in the fields list
		const fieldForm =  field.buildForm();

		//give fieldset id and ordinal
		const fieldSet: FieldSetEditorModel = new FieldSetEditorModel();
		const fieldSetId = Guid.create().toString();
		fieldSet.id = fieldSetId;
		fieldSet.ordinal = afterOrdinal < 0? 0 :afterOrdinal;

		const parentArray = this.form.get('fieldSets') as FormArray;

		parentArray.controls.forEach(fieldset=>{
			const ordinalControl = fieldset.get('ordinal');
			const ordinalValue = ordinalControl.value;
			if(ordinalValue > afterOrdinal){
				ordinalControl.setValue(ordinalValue +1);
			}
		});
		const fieldsetForm = fieldSet.buildForm();
		(fieldsetForm.get('fields') as FormArray).push(fieldForm);

		const index = afterOrdinal < 0 ? 0: afterIndex +1;
		parentArray.insert(index, fieldsetForm);
		this.dataNeedsRefresh.emit();

		// this.selectedFieldSetId = fieldSetId;
		setTimeout(() => {
			this.selectedFieldSetId = fieldSetId;
		}, 200);
	}

	private _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;
	}
}
