import { ChangeDetectorRef, Component, inject, OnDestroy, OnInit, signal, ViewChild } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import {DialogService, DynamicDialogRef} from 'primeng/dynamicdialog';
import {DynamicDialogConfig} from 'primeng/dynamicdialog';
import { FormControl, ReactiveFormsModule, UntypedFormBuilder, Validators } from '@angular/forms';
import { Subject, Subscription} from 'rxjs';
import { ConfirmationService, MessageService } from 'primeng/api';
import { DatePickerModule } from 'primeng/datepicker';
import { Code, RelationShipView, Person, mState, RelationShip, PersonPhotoDto}  from '../models';
import { AppSettingService, LookupService, Utils } from '../shares';
import { PersonService } from './person.service';
import { ButtonModule } from 'primeng/button';
import { SelectModule } from 'primeng/select';
import { CheckboxModule } from 'primeng/checkbox';
import { InputTextModule } from 'primeng/inputtext';
import moment from 'moment';
import { HttpEvent } from '@angular/common/http';
import { TableModule } from 'primeng/table';
import { Pickperson } from '../pickperson/pickperson';
import { ImageDisplayComponent } from '../pickperson/image.display';
import { TooltipModule } from 'primeng/tooltip';
import { AutoFocusModule } from 'primeng/autofocus';
import { DomSanitizer } from '@angular/platform-browser';
import { PhotoList } from '../attachphoto/photolist';

export interface FileUploadEvent {
  originalEvent: HttpEvent<any>;
  files: File[];
};
export interface FileUploadHandlerEvent {
  files: File[];
};

@Component({
templateUrl: 'person.edit.html',
selector: 'person-edit',
imports:[ButtonModule,TableModule,ReactiveFormsModule,TooltipModule,
	AutoFocusModule,
	SelectModule,CheckboxModule, InputTextModule,DatePickerModule],
styleUrls: ['person.edit.css'],
providers: [DialogService]

})
export class PersonEdit implements OnInit, OnDestroy {
	editRef: DynamicDialogRef | undefined;
	 private sanitizer = inject(DomSanitizer);
	 imageDataUrl = signal<string>("");
	returnUrl ='';
	loginUser ='';
	hostsite ='';
	_error ='';
	_id= -1;
	_partnerId = -1;
	fatherList: Code[] =[];
	motherList: Code[] =[];
	sexList:Code[] =[];
	familyList: Person[] =[];
	profileFile: File | null = null;
	photoList: PersonPhotoDto[] = [];
  	fileName = '';
	isNew = false;
	validationPoints?: Code[];
	partners = signal<RelationShipView[]>([]);
	deletePartner: RelationShipView[] =[];
	msg="[Family Edit Component] ";
	private formBuilder = inject(UntypedFormBuilder);
	private personService = inject(PersonService);
	private messageService = inject(MessageService);
	private confirmationService = inject(ConfirmationService);
	//for focus input
//	@ViewChild('mystaffid') mystaffNo!: MatInput;
	isChange = true; // disable use false//true for not disable. make sure it true is disable button.
	private subscription:Subscription = new Subscription();
	subChanged$ = new Subject<boolean>();
	adminuserForm = this.formBuilder.group({
		id: [0], //Validators.required
		email: [''], //Validators.required
		firstname: ['',Validators.required], //Validators.required
		lastname: ['',Validators.required], //Validators.required
		phone: [''], //Validators.required
		address: [''],
		sex:['M',Validators.required],
		image: [''],
		dob: new FormControl<Date|null>(null),
		alive: [false], //Validators.required
		fatherId:[0],
		motherId:[0]

		
	
	});
constructor( private cdr: ChangeDetectorRef,public dialogService: DialogService,
	public ref: DynamicDialogRef, public config: DynamicDialogConfig,

	private router: Router, private route: ActivatedRoute,
	 private appSetting: AppSettingService,
	) {
		this.hostsite = this.appSetting.appSetting.attachment;
	}
	loadParentList( list: Person[], selfId: number): void {
		this.familyList = list;
		let i = 0;
		let item: Code;
		let family: Person;
		//const list = this.familyService.parentList;
		for (i = 0; i < list.length; i++)
		{
			family= list[i];
			if (family.id != selfId)
			{
				item = { id: family.id,
					name: family.firstName! + " " + family.lastName!,
					status: family.lastName!,
					active: family.alive!
					
				};
				if (family.sex == 'F')
					this.motherList.push(item);
				else
					this.fatherList.push(item);

			}
		}

		
	}

getClassForRequire(prev:string,name:string){
  const notok = !this.adminuserForm.controls[name].valid &&
   this.adminuserForm.controls[name].touched;
  let str =prev;
  if (notok)
    str += " ng-invalid ng-dirty";
  return str;
}
dislayImage(): any {
	if (this.profileFile)
	{
		return URL.createObjectURL(this.profileFile);
	}
	else if (this.imageDataUrl() != "")
	{
		return this.imageDataUrl();
	}
	
	return null;
}

onFileSelected(event: any) {

    const file: File = event.target.files[0];

    if (file) {
      this.profileFile = file;
      //this.messageService.add({ severity: 'info', summary: 'Success', detail: 'File Uploaded!' });
      this.adminuserForm.patchValue({ image: this.profileFile.name });
      this.fileName = file.name;
      this.subChanged$.next(false);
    }
  }

deleteFile(): void {
	this.confirmationService.confirm({
            
            message: 'Are you sure that you want to delete image?',
            header: 'Confirmation',
            closable: true,
            closeOnEscape: true,
            icon: 'pi pi-exclamation-triangle',
            rejectButtonProps: {
                label: 'Cancel',
                severity: 'secondary',
                outlined: true,
            },
            acceptButtonProps: {
                label: 'Delete',
            },
            accept: () => {
               this.doDeleteFile();
            },
           
        });
}

doDeleteFile(): void {
    const fileName = this.adminuserForm.value.image;
	if (fileName)
	{
		this.doDeleteImage(fileName);
	}
	else if (this.profileFile)
		this.profileFile = null;
}
doDeleteImage(fileName:string) : void {
	const familyId = this.adminuserForm.value.id;
    const data = { fileName, familyId };
    const delete$ = this.personService.deleteUploadFile(data);
    this.subscription.add(delete$.subscribe(
      {
        next: x => {
          if (x.statusCode == 1) {
            {
              this.adminuserForm.patchValue({ image: "" });
			  this.cdr.detectChanges();
			  this.messageService.add({ severity: 'success', summary: 'Delete image all ok', detail: 'file: ' + fileName });
            }
          }
          else {
            this.messageService.add({ severity: 'error', summary: 'Error delete upload file', detail: 'Fail to delete upload file: ' + x.message });
          }
        },
        error: e => {
          this.messageService.add({ severity: 'error', summary: 'Error delete upload file', detail: 'Fail to delete upload file: ' + e });
        }
      }
    ));
  }

getFileToSave(file: File): FormData {

    //const familyId = this.adminuserForm.value.id!;
    const formData = new FormData();
    formData.append("file", file);
	return formData;
  }
   // formData.append("familyId", familyId.toString());   
   // console.log("upload file", familyId, file);
saveFile(formData: FormData)
{
    const upload$ = this.personService.uploadFile(formData);
    this.subscription.add(upload$.subscribe(
      {
        next: x => {
          if (x.statusCode == 1) {
            const filename = x.data;
            //this.messageService.add({ severity: 'info', summary: 'Success', detail: 'File Uploaded to server API: ' + x.data });
            this.adminuserForm.patchValue({ image: filename });
            this.cdr.detectChanges();
          }
          else
            this.messageService.add({ severity: 'error', summary: 'Error upload file', detail: 'Fail to upload file: ' + x.message });
        },
        error: e =>
          this.messageService.add({ severity: 'error', summary: 'Error upload file', detail: 'Fail to upload file: ' })

      }
    ));
}

populateSex(): void {
	let item: Code;
	item = {
		id:1,
		name:"Female",
		status:'F'
	};
	this.sexList.push(item);
	item = {
		id:2,
		name:"Male",
		status:'M'
	};
	this.sexList.push(item);
}

ngOnInit():void {
	this.populateSex();
    const id = this.config.data.id;   
	console.log("family edit", this.config);
    this.loadParentList(this.config.data.familyList, id);
	//this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/';
//	const id = Number(this.route.snapshot.paramMap.get('id'));
	// now load thing up
	const user = Utils.getCurrentUser();
//	console.log(this.msg + "current login user ", user);
	if (user.username === '')
		alert("you are not login.");
	else
		this.loginUser = user.firstName;
	this._id = id;
	//console.log(this.msg + " " + id );
	this.subscription.add(this.adminuserForm.valueChanges.subscribe(x => this.isChange = false));
    this.subscription.add(this.subChanged$.subscribe(x => this.isChange = x));
	if (id > 0)
	{
		this.isNew = false;
	   this.subscription.add(
	   this.personService.loadPersonById(id).subscribe({
		next: x => this.assignValue(x.data), 
		error: e => console.log(e)
		})
		);
  	}
	else
	{
		this.isNew = true;
	}
	
}

// this for disable submit button
get isFieldsChange() {
    const chan = this.isChange || !this.adminuserForm.valid; // this disable so need true valid = true not
	console.log(this.msg + 'is fields change', chan);
    return chan;
}

doViewImage(imageName:string): void {
	const ref = this.dialogService.open(ImageDisplayComponent, {
      data: {         
         imageName,         
    	},	  
      header: 'View Image',
	  draggable: true,
      width: '70%',	  
	  modal:true,
      maximizable: true
    });
    
    ref.onClose.subscribe((item: Person) => {
      if (item) {
        //console.log("after close ward edit", item);
        this.messageService.add({severity:'success', summary: 'Select', detail: item.firstName!});
       //update the current list
        
      }
      });
}

assignValue(item:Person): void {
	this._id = item.id;
	this.fileName = item.image!;
	if (item.relationShips)
		this.populatePartner(item.relationShips, item.id);
	if (item.personPhotos)
	{
		this.photoList = item.personPhotos;
	}
	this.adminuserForm.patchValue({
		id: item.id,
		email: item.email,
		firstname: item.firstName,
		lastname: item.lastName,
		alive: item.alive,
		phone: item.phone,
		address: item.address,
		fatherId: item.fatherId,
		motherId: item.motherId,
		sex: item.sex,
		image: item.image
		});
		const dob = item.dob;
		if (dob)
		{
			this.adminuserForm.patchValue({
				dob: moment(dob).toDate()
			});
		}
		if (item.image && item.image.length > 0)
		{
			this.loadImage(item.image);
		}
		// disable use false//true for not disable.
		this.subChanged$.next(true);
	}
 
	// convenience getter for easy access in form fields
	get f() { return this.adminuserForm.controls;}
	
	loadImage(fileName: string| null): void {
    const download = this.personService.downloadFile(fileName!);
    this.subscription.add(download.subscribe({
      next: x => {
        if (x.statusCode == 1)
        {
			
          this.displayIamge64(x.data);
        
        }
        else
        {
          console.log("error in download in api ", x.message);
        }
      },
      error: e => console.error("error in download image", e)
    }));
  }
  displayIamge64(baseImage: string): void 
  { 
    const changeUrl = (this.sanitizer.bypassSecurityTrustResourceUrl(baseImage) as any).changingThisBreaksApplicationSecurity;
    console.log('this is bypassSecurityTrustResourceUrl', changeUrl);
    const fullDataUri = `data:image/png;base64,${changeUrl}`;
    this.imageDataUrl.set(fullDataUri);
  }
 validate(adminuser:Person): boolean {
	let result = true;
	console.log("validate", adminuser);
	if (!adminuser.firstName)
	{
		this._error = 'firstname is blank or empty';
		result = false;
	}
	else if (adminuser.lastName == '')
	{
		this._error = 'lastname is blank or empty';
		result = false;
	}
	return result;
 }

 getPartnerForSave(): RelationShip[] {
   let rlist: RelationShip[]= [];
   let i =0;
   let vitem: RelationShipView;
   let item: RelationShip;
   for (i = 0; i < this.deletePartner.length; i++)
   {
		vitem = this.deletePartner[i];
		item = {
			id: vitem.id,
			personId: vitem.personId,
			state: mState.Delete,
			relatePersonId: vitem.relatePersonId
		};
		rlist.push(item);
		console.log("get partner for save delete list ", vitem);
   }
   console.log("get partner for save before loop this.partners ", i);
   for (i = 0; i < this.partners().length; i++)
   {
		vitem = this.partners()[i];
		if (vitem.state == mState.New || vitem.state == mState.Modified)
		{
			item = {
				id: vitem.id,
				personId: vitem.personId,
				state: vitem.state,
				relatePersonId: vitem.relatePersonId
			};
			rlist.push(item);
		}
		console.log("get partner for save in partner list ", vitem);
   }
   return rlist;
 }

 async onSubmit(e:Event): Promise<void> {
	    e.preventDefault();
		// if form valid then go save
		//make sure 
		const okToSave = this.adminuserForm.valid;
		if (okToSave)
		{
			let adminuserValue = this.adminuserForm.value;
			
			let item:Person = {
				id: adminuserValue.id,
				email: adminuserValue.email,
				firstName: adminuserValue.firstname,
				lastName: adminuserValue.lastname,
				alive: adminuserValue.alive,				
				phone: adminuserValue.phone,
				address: adminuserValue.address,
				image:adminuserValue.image,
				fatherId: adminuserValue.fatherId,
				motherId: adminuserValue.motherId,
				sex: adminuserValue.sex
			};
			
			if (adminuserValue.dob)
			{
				item.dob = moment(adminuserValue.dob).format("YYYY-MM-DD");
			}

			this._error ='';
			const allOK = this.validate(item);
			if (allOK)
			{
				let container:any = {
					person: item
				};
				if (this.profileFile != null)
				{
					container.formData = await Utils.toBase64(this.profileFile);
					container.fileName = this.profileFile.name;
					console.log('image as base64 ', container);
				}
				container.person.relationShips = this.getPartnerForSave();
				this.subscription.add (
					this.personService.savePerson(container).subscribe({
						next:  	x => {
							if (x.statusCode >= 1)
							{
								item.id = x.data;
							//	this.messageService.add({severity:'success', summary: 'Save user', detail: item.firstName + " " + item.lastName });
								//this.router.navigate([this.returnUrl]);
								console.log("the person after save", item);
								const list = this.getPhotoListforSave();
								if (list.length > 0)
								{
									this.savePhotoList(list, item);
								}
								else
									this.ref.close(item);
							}
							else
							{
							this.messageService.add({severity:'error', summary: 'Error', detail: x.message });  
							}
						},
						error: e => {      
							const message = e.message;
							this.messageService.add({severity:'error', summary: 'Error', detail: message });  
							console.error("error ", e);
						} 
					})
				);
			}
			else
				this.messageService.add({severity:'error', summary: 'Error', detail: this._error });
		}
}
getFamilyById(id: number): Person | undefined {
	let result:Person |undefined;
	result = this.familyList.find(x => x.id == id);
	return result;
}
populatePartner(list: RelationShip[], personId: number): void {
	let item: RelationShip;
	let vitem: RelationShipView;
	let vlist: RelationShipView[] =[];
	let i = 0; 
	let family:Person|undefined;
	for (i = 0; i < list.length; i++)
	{
		item = list[i];
		if (item.relatePersonId != personId)
		{
			family = this.getFamilyById(item.relatePersonId);
		}
		else 
		{

			family = this.getFamilyById(item.personId);
		}
		if (family)
		{
			vitem = {
				id: item.id,
				personId: item.personId,
				relatePersonId: item.relatePersonId,
				pfirstName: family.firstName,
				plastName: family.lastName,
				sex: family.sex,
				state:mState.NoChange
			};
			vlist.push(vitem);
		}
	}
	if (vlist.length > 0)
		this.partners.set(vlist);
}
viewAttachment(): void {
	this.showAttachment("Add family photo or other");
}

addPartner(): void {
	const title = "Partner";
	this.showPickPerson(title, (sfamily: Person) => {
		let item: RelationShipView = {
		id: this._partnerId--,
		state: mState.New,
		personId: this._id,
		relatePersonId: sfamily.id,
		pfirstName: sfamily.firstName,
		plastName: sfamily.lastName,
		sex: sfamily.sex,
	};
	const fm = this.partners();
	fm.push(item);
	this.partners.set(fm);
	this.subChanged$.next(false);
	console.log("after put in partners list", this.partners());
	});
}

onDeletePartner(item:RelationShipView): void {
		this.confirmationService.confirm({
            
            message: 'Are you sure that you want to delete partner?',
            header: 'Confirmation',
            closable: true,
            closeOnEscape: true,
            icon: 'pi pi-exclamation-triangle',
            rejectButtonProps: {
                label: 'Cancel',
                severity: 'secondary',
                outlined: true,
            },
            acceptButtonProps: {
                label: 'Delete',
            },
            accept: () => {
               this.doDeletePartner(item);
            },
           
        });
}

doDeletePartner(item:RelationShipView): void {
	if (item.id > 0)
	{
		this.deletePartner.push(item);
	}
	const dlist = this.partners().filter(x => x.id != item.id);
	this.partners.set(dlist);
	console.log("after delete partners list", this.partners());
	this.subChanged$.next(false);
}

showPickPerson(title:string, callback:(id: Person) => void) :void {
	const ref = this.dialogService.open(Pickperson, {
      data: {         
         familyList: this.familyList,         
    },
      header: title,
      width: '80%',
	  draggable: true,
      maximizable: true
    });
    
    ref.onClose.subscribe((item: Person) => {
      if (item) {
        //console.log("after close ward edit", item);
        this.messageService.add({severity:'success', summary: 'Select', detail: item.firstName!});
       //update the current list
        callback(item);
      }
      });
}

showAttachment(title:string): void {
	const ref = this.dialogService.open(PhotoList, {
      data: {         
         id: this._id,  
		 personPhotos: this.photoList       
    },
      header: title,
      width: '80%',
	  draggable: true,
      maximizable: true
    });
    
    ref.onClose.subscribe((ritem: any) => {
	 const item = ritem.list;
	 const deleteIds = ritem.deleteIds;
      if (item) {
        console.log("after close " + title, item);
		if (item.length > 0)
		{
        	this.messageService.add({severity:'success', summary: title, detail: "photo attachment " + item.length});
		}
       //update the current list
      //  callback(item);	    
	    this.updatePhotoList(item);
      }
	  if (deleteIds && deleteIds.length > 0)
	  {
		let j = 0;
		
		for (let i = 0; i < deleteIds.length; i++)
		{
			const id = deleteIds[i];
			j = this.photoList.findIndex(x => x.id == id);
			if (j > -1)
			{
				this.photoList.splice(j,1);
			}

		}
		this.cdr.markForCheck();
	  }

	 });
}

updatePhotoList(list: PersonPhotoDto[]): void {
	for (let i = 0; i < list.length; i++)
	{
		const item = list[i];
		const idx = this.photoList.findIndex(x => x.id == item.id);
		if (idx && idx < 0)
			this.photoList.push(item);
		else
		{
			let eitem = this.photoList[idx];
			eitem.photo = item.photo;
			eitem.photoType = item.photoType;
			eitem.file = item.file;
		}
	}

	console.log("the photos after close", this.photoList);
	this.subChanged$.next(false);//make save button to enable.
	this.cdr.markForCheck();
}

getPhotoListforSave(): PersonPhotoDto[] {
	let result: PersonPhotoDto[] =[];
	for (let i = 0; i < this.photoList.length; i++)
	{
		if (this.photoList[i].id < 0)	
		{
			result.push(this.photoList[i]);
		}
	}
	return result;
}

savePhotoList(list: PersonPhotoDto[], item:Person): void {
	
		const formData = new FormData();
		for (let i = 0; i < list.length; i++)
		{
			const file = list[i].file;
			if (file)
				formData.append("files", file, file.name);
		}
		formData.append('personId', this._id.toString());

		const personPhoto$ = this.personService.savePersonPhotoList(formData);
		this.subscription.add(personPhoto$.subscribe(
		{
			next: x => {
			if (x.statusCode == 1) {
				//const filename = x.data;            
				//this.adminuserForm.patchValue({ image: filename });
				this.ref.close(item);
				//this.cdr.detectChanges();
			}
			else
				this.messageService.add({ severity: 'error', summary: 'Error save attach photos files', detail: 'Fail to photos file: ' + x.message });
			},
			error: e =>
			this.messageService.add({ severity: 'error', summary: 'Error attach photos file', detail: 'Fail to photos file: ' })

		}
		));
	
}

cancel(e:Event):void {
    e.preventDefault();
    this.ref.close(null);
  }
ngOnDestroy() {
	this.subscription.unsubscribe();
}
}
