import React from "react";
import _ from 'lodash';
import { buildEmptyObject } from "../../../../auto/js/widgets/FormComponent";
import { getServiceUri, metadataLoader, pojoMetadata } from "../../../../auto/js/metadata";
import { MTLB_TYPE_ADOPTION } from "../../../../auto/js/metadata/MtlbType";
import { rest } from "../../../../auto/js/services/RestClient";
import { t } from '../../../../auto/js/services/i18ndb';
import { showNotification, swapObject } from "../../../../auto/js/utils";
import * as Yup from 'yup';
import { Section } from "../../widgets/Section";
import { AddressComponent } from "../../../../auto/js/widgets/AddressComponent";
import { PersonComponent } from "../../../../auto/js/widgets/PersonComponent";
import { loadPersonData } from "../../utils";
import { GeoDataComponent } from "../../../../auto/js/widgets/GeoDataComponent";
import { AdvancedSearchPersonComponent } from "../../widgets/AdvancedSearchPersonComponent";
import { CountryAutoCompleteInput } from "../../widgets/CountryAutoCompleteInput";
import AutocompleteListSelector from "../../widgets/AutocompleteListSelector";
import { geoDataMetadataLoader } from "../../../../auto/js/metadata/GeoDataMetadataLoader";
import { TypeOfAcquisition } from "../../../../auto/js/metadata/TypeOfAcquisition";
import { DELETE_ATTACHMENT_EVENT } from "../../../../auto/js/events/Gui";

const gender = {1:"MALE", 2:"FEMALE"};
const maritalStatus = {1:"SINGLE", 2:"MARRIED", 3:"DIVORCED", 4:"WIDOWED"};

export const adoptionApplicationFields = [
	{name: "tags", type:"tags", x:1, y:1, layout:"col-md-12"},
	{name: "citizenDetails", type: "custom", x:1, y:2, layout:"col-md-12", component: (name, disabled) => <Section name={name} />},
	{name: "image", type: "image", x: 1, y: 3, layout: "col-md-12" },
	{name: "vitalRecordId", type:"number", x: 1, y: 4, layout: "col-md-6" },
	{name: "firstname", type: "text", x:2, y:6, layout:"col-md-6",
		"validation": Yup.string().nullable().default(undefined).min(2, t`First name must be at least two characters long`).max(14, t`First name must be less than fifteen characters long`).required(t`First name is required`).matches(/[\p{Letter}\p{Mark}\s]+$/u, t`Only alphabets are allowed for this field `).matches(/^\p{Lu}.*$/u, t`First letter need to be Upper Case`)},
	{name: "secondname", type: "text", x:2, y:5, layout:"col-md-6",
		"validation": Yup.string().nullable().default(undefined).min(2, t`Middle name must be at least four characters long`).max(28, t`Middle name must be less than twenty eight characters long`).matches(/^\p{Lu}.*$/u, t`First letter need to be Upper Case`)},
	{name: "thirdname", type: "text", x:1, y: 6, layout:"col-md-6",
		"validation": Yup.string().nullable().default(undefined).min(2, t`Melanisian name must be at least four characters long`).max(14, t`Melanisian name must be less than fifteen characters long`).matches(/[\p{Letter}\p{Mark}\s]+$/u, t`Only alphabets are allowed for this field `).matches(/^\p{Lu}.*$/u, t`First letter need to be Upper Case`)},
	{name: "fourthname", type: "text", x:1, y: 5, layout:"col-md-6",
		"validation": Yup.string().nullable().default(undefined).min(2, t`Family name must be at least four characters long`).max(14, t`Family name must be less than fifteen characters long`).required(t`Family name is required`).matches(/[\p{Letter}\p{Mark}\s]+$/u, t`Only alphabets are allowed for this field `).matches(/^\p{Lu}.*$/u, t`First letter need to be Upper Case`)},
	{name: "fifthname", type: "text", x:1, y: 7, layout:"col-md-6",
		"validation": Yup.string().nullable().default(undefined).min(2, t`Marriage name must be at least four characters long`).max(14, t`Marriage name must be less than fifteen characters long`).matches(/[\p{Letter}\p{Mark}\s]+$/u, t`Only alphabets are allowed for this field `).matches(/^\p{Lu}.*$/u, t`First letter need to be Upper Case`)},
	{name: "gender", type: "select", x:1, y: 8, layout:"col-md-6", metadata: () => gender,
		"validation": Yup.string().nullable().default(undefined).required(t`Gender is required`)},
	{name: "maritalStatus", type: "select", x:2, y:8, layout:"col-md-6", metadata: () => maritalStatus},
	{name: "birthdate", type: "date", x:1, y: 9, layout:"col-md-6",
		"validation": Yup.date().nullable().default(undefined).required('A date of birth is required')
	},
	{name: "birthTime", type: "time", x:2, y:9, layout:"col-md-6"},
	{name: "birthDayUnknown", type: "checkbox", x:1, y:10, layout:"col-md-4"},
    {name: "birthMonthUnknown", type: "checkbox", x:2, y:10, layout:"col-md-4"},
    {name: "birthYearUnknown", type: "checkbox", x:3, y:10, layout:"col-md-4"},	
	{name: "disability", type: "checkbox", x:1, y:11, layout:"col-md-6"},
	{name:"citizenshipBox", label: "Citizenship", components: [
		{name: "primaryCitizenship", type:"custom", x:1, y:1, layout:"col-md-6", component: (name, disabled) => <CountryAutoCompleteInput name={name} readOnly={disabled} default={"191"}/>},
		{name: "typeOfAcquisition", type:"select", x:2, y:1, layout:"col-md-6", metadata: () => swapObject(TypeOfAcquisition)},
		{name: "otherCitizenshipCsv", type: "custom", x:1, y:3, layout: "col-md-6", component: (name, disabled) => <AutocompleteListSelector options={geoDataMetadataLoader.getRootNodes()} name={name} readOnly={disabled} label={t`otherCitizenship`} />},
	], type: "box", x:2, y:12, layout:"col-md-11 ms-2 mt-2 pt-1 pb-2"},
	{name:"birthBox", label: "Birth Place", components: [
		{name: "birthPlace", type: "custom", x:1, y:1, layout:"col-md-12", component: (name, disabled) => <GeoDataComponent name={name} disabled={disabled} default={"191"}/>}
	 ], type: "box", x:2, y:13, layout:"col-md-11 ms-2 mt-2 pt-1 pb-2"},
	 {name:"originBox", label: "Village Of Origin", components: [
		{name: "villageOfOrigin", type: "custom", x:1, y:1, layout:"col-md-12", component: (name, disabled) => <GeoDataComponent name={name} disabled={disabled} default={"191"}/>},
	], type: "box", x:1, y:14, layout:"col-md-6 ms-2 mt-2 pt-1 pb-2"},
	{name: "birthMotherDetails", type: "custom", x:1, y:16, layout:"col-md-12", component: (name, disabled) => <Section name={name} />},
	{name:"motherInfo", options: [
        {"name":"motherWithBirthRecord","label":"Birth Mother With Record"},
        {"name":"motherWithoutBirthRecord","label":"Birth Mother Without Record"},
		{"name":"unknownMother","label":"Unknown Birth Mother"},
    ], type: "radio", x:1, y:17, layout:"col-md-12 pt-4"},
	{name: "motherId", label: "Search Birth Mother", type: "custom", x:1, y:17, layout:"col-md-12",
	 	component: (name, disabled) => <AdvancedSearchPersonComponent name={name} label={"Search Birth Mother"} readOnly={disabled} loadData={loadPersonData}/>,
		display: (data) => {return (data.motherInfo === "motherWithBirthRecord" || data.motherId != null)?true: false;}},
	{name: "reportedMotherName", type: "text", x:2, y:17, layout:"col-md-12",
		display: (data) => {return data.motherInfo === "motherWithoutBirthRecord"?true: false;}
	},
	{name: "birthFatherDetails", type: "custom", x:1, y:18, layout:"col-md-12", component: (name, disabled) => <Section name={name} />},
	{name:"fatherInfo", options: [
        {"name":"fatherWithBirthRecord","label":"Birth Father With Record"},
        {"name":"fatherWithoutBirthRecord","label":"Birth Father Without Record"},
		{"name":"unknownFather","label":"Unknown Birth Father"},
    ], type: "radio", x:1, y:20, layout:"col-md-12 pt-4"},
	{name: "fatherId", label: "Search Birth Father", type: "custom", x:1, y:21, layout:"col-md-12",
	 	component: (name, disabled) => <AdvancedSearchPersonComponent name={name} label={"Search Birth Father"} readOnly={disabled} loadData={loadPersonData}/>,
		display: (data) => {return (data.fatherInfo === "fatherWithBirthRecord" || data.fatherId != null)?true: false;}},
	{name: "reportedFatherName", type: "text", x:2, y:22, layout:"col-md-12",
		display: (data) => {return data.fatherInfo === "fatherWithoutBirthRecord"?true: false;}
	},
	{name: "newAdoptionDetails", type: "custom", x:1, y:23, layout:"col-md-12", component: (name, disabled) => <Section name={name} />},
	{name: "notChangingMother", type: "checkbox", x:1, y: 24, layout:"col-md-12"},
	{name: "adoptiveMotherId", label: "Search Adoptive Mother", type: "custom", x:1, y:25, layout:"col-md-12",
	 	component: (name, disabled) => <AdvancedSearchPersonComponent name={name} label={"Search Adoptive Mother"} readOnly={disabled} loadData={loadPersonData}/>,
		display: (data) => {return !data.notChangingMother}
	},
	{name: "motherAdoptionDate", type: "date", x:1, y: 26, layout:"col-md-6", display: (data) => {return !data.notChangingMother}},
	{name: "notChangingFather", type: "checkbox", x:1, y: 27, layout:"col-md-12"},
	{name: "adoptiveFatherId", label: "Search Adoptive Father", type: "custom", x:1, y:28, layout:"col-md-12",
	 	component: (name, disabled) => <AdvancedSearchPersonComponent name={name} label={"Search Adoptive Father"} readOnly={disabled} loadData={loadPersonData}/>,
		display: (data) => {return !data.notChangingFather}
	},
	{name: "fatherAdoptionDate", type: "date", x:1, y: 29, layout:"col-md-6", display: (data) => {return !data.notChangingFather}},
	{name: "courtAdoptionNumber", type: "text", x:1, y: 30, layout:"col-md-12"},
	{name: "previousAdoptiveFatherDetails", type: "custom", x:1, y:31, layout:"col-md-12", component: (name, disabled) => <Section name={name} />,
		display: (data) => {return data.prevFatherId}
	},
	{name: "prevFatherId", label: "", type: "custom", x:1, y:32, layout:"col-md-12",
		component: (name, disabled) => <AdvancedSearchPersonComponent name={name} label={""} readOnly={true} loadData={loadPersonData}/>,
		display: (data) => {return data.prevFatherId}
	},
	{name: "fatherEndAdoptionDate", type: "date", x:1, y: 33, layout:"col-md-6", display: (data) => {return data.prevFatherId}},
	{name: "previousAdoptiveMotherDetails", type: "custom", x:1, y:34, layout:"col-md-12", component: (name, disabled) => <Section name={name} />,
		display: (data) => {return data.prevMotherId}
	},
	{name: "prevMotherId", label: "", type: "custom", x:1, y:35, layout:"col-md-12",
		component: (name, disabled) => <AdvancedSearchPersonComponent name={name} label={""} readOnly={true} loadData={loadPersonData}/>,
		display: (data) => {return data.prevMotherId}
	},
	{name: "motherEndAdoptionDate", type: "date", x:1, y: 36, layout:"col-md-6", display: (data) => {return data.prevMotherId}},

	{name: "medicalNotificationFile", label:"Medical Notification", type: "file", x:1, y:37, layout:"col-md-12", 
		uploadUrl: (id) => getUploadUrl(id), 
        previewUrl: (id) => getPreviewUrl(id),
		loadData: async (id) => loadMedicalNotificationAttachment(id), 
		handleDelete:(id) => handleMedicalNotificationDelete(id), 
		handleClick: (id) => handleMedicalNotificationClick(id),
		updateFileData: (data) => updateFileData(data)
	},
	{name: "Mentions", type: "custom", x:1, y:38, layout:"col-md-12", component: (name, disabled) => <Section name={name} />},
    {name: "mentions", type: "text", x:1, y:39, layout:"col-md-12"},
	{name: "Extras", type: "custom", x:1, y:40, layout:"col-md-12", component: (name, disabled) => <Section name={name} />},
    {name: "notes", type: "text", x:1, y:41, layout:"col-md-12"}
];

const getUploadUrl = (id) => {
	return getServiceUri() + 'civil-status-mtlb/medical-notification-file' + '/' + id;
}

const getPreviewUrl = (id) => {
	return getServiceUri() + 'civil-status-mtlb/medical-notification-file' + '/preview/' + id;
}

const updateFileData = (data) => {
	let filter = {name: data.fileName, description: data.description};
	rest.request(getServiceUri() + 'civil-status-mtlb/medical-notification-file' + '/' + data.id, "PUT", filter);
}

const handleMedicalNotificationClick = async (id) => {
	const token = await rest.getToken(getServiceUri() + 'token/get-auth-code');
	window.location = getServiceUri() + 'civil-status-mtlb/medical-notification-file' + '/' + id + '/' + token;
};
const handleMedicalNotificationDelete = (id) => {
	rest.delete('civil-status-mtlb/medical-notification-file', id).then(() => {
		DELETE_ATTACHMENT_EVENT.publish(id)
	});
};

const loadMedicalNotificationAttachment = async (id) => {
	let filter = {and: true};
	filter['civil-status-mtlb-medical-notification-file'] = {};
	filter['civil-status-mtlb-medical-notification-file']['civilStatusMtlbId'] = id;
	return rest.search('civil-status-mtlb/medical-notification-file', filter)
}

export const saveAdoptionApplicationForm = async (formData) => {
	let data = _.clone(formData);
	let dto = pojoMetadata['civil-status-mtlb'].form2dto(data);
	dto.mtlbType = MTLB_TYPE_ADOPTION;
	dto.vitalRecordId = formData.id;
	dto.id = null;
	if (formData.faceId && formData.faceId != null) {
		return rest.read('face', formData.faceId).then(faceObject => {
			dto.face = faceObject.image;
			dto.faceMimeType = faceObject.faceMimeType;
			if (formData.birthCountry)
				dto.birthCountry = formData.birthCountry.key;
			try {
				return rest.request(getServiceUri() + 'apply/create-civil-status-mtlb', 'POST', dto)
			} catch (err) {
				alert(err);
			}
		})
	}
	else {
		if (!formData.image.isEmpty) {
			let base64Image = formData.image.url;
			let faceMimeType = base64Image.substring(base64Image.indexOf(':') + 1, base64Image.indexOf(';'))
			let base64 = base64Image.substr(base64Image.indexOf(',') + 1);
			dto.face = base64;
			dto.faceMimeType = faceMimeType;
		}
		if (formData.birthCountry)
			dto.birthCountry = formData.birthCountry.key;
		try {
			return rest.request(getServiceUri() + 'apply/create-civil-status-mtlb', 'POST', dto)
		} catch (err) {
			alert(err);
		}
	}
}

export const loadAdoptionApplicationFormData = async (id) => {
	return await rest.read('civil-status-mtlb', id).then(response => {
		let form = response;
		let face = null;
		if (response.face != null) {
			let mimeType = response['faceMimeType'];
			face = "data:".concat(mimeType, ";base64,", response.face)
		}
		if (response.birthCountry != null) {
			let countryMetadata = metadataLoader.get('country');
			form.birthCountry = {key: response.birthCountry, value: countryMetadata[response.birthCountry]}
		}
		if (response.secondname != null) {
			form['middlename'] = response.secondname;
			if (response.thirdname != null)
				form['middlename'] = form['middlename'] + " " + response.thirdname;
		}
		if (response.birthTime !== null)
			response.birthTime = new Date().setHours(response.birthTime[0], response.birthTime[1]);
		form['image'] = {x: 0.5, y:0.5, scale: 1, rotate: 0, url: (face != null)?face: '/public/avatar.png', isEmpty: true};


		let tagFilter = {and: true};
		tagFilter['civil-status-mtlb-tag'] = {civilStatusMtlbId: id};
		
		return rest.search('civil-status-mtlb-tag', tagFilter).then(tags => {
			form['tags'] = tags
			
			return form;
		})
	})
}

export const updatePendingAdoptionApplicationForm = async (formData) => {
	let dto = pojoMetadata['civil-status-mtlb'].form2dto(formData);
	form2dto(formData, dto);
	try {
		return rest.request(getServiceUri() + 'civil-status-mtlb/pending/update', 'POST', dto);
	} catch (err) {
		alert(err);
	}
}

export const updateAdoptionApplicationForm = async (formData) => {
	let dto = pojoMetadata['civil-status-mtlb'].form2dto(formData);
	form2dto(formData, dto);
	try {
		return rest.update('civil-status-mtlb', dto);
	} catch (err) {
		alert(err);
	}
}

export const deleteAdoptionApplicationForm = async (id) => {
	try {
		return rest.delete('civil-status-mtlb', id);
	} catch (err) {
		alert(err);
	}
}

export const updateRejectedAdoptionApplicationForm = async (formData) => {
	//TODO: Move form2dto from pojo metadata
	let dto = pojoMetadata['civil-status-mtlb'].form2dto(formData);
	form2dto(formData, dto);
	try {
		return rest.request(getServiceUri() + 'civil-status-mtlb/rejected/update', 'POST', dto);
	} catch (err) {
		alert(err);
	}
}

export const rejectAdoptionApplicationForm = async (id) => {
	try {
		return rest.request(getServiceUri() + 'civil-status-mtlb/pending/reject', 'POST', id);
	} catch (err) {
		alert(err);
	}
}

export const rejectReadyAdoptionApplicationForm = async (id) => {
	try {
		return rest.request(getServiceUri() + 'civil-status-mtlb/ready/reject', 'POST', id);
	} catch (err) {
		alert(err);
	}
}

export const approveReadyAdoptionApplicationForm = async (id) => {
	try {
		return rest.request(getServiceUri() + 'civil-status-mtlb/ready/approve', 'POST', id);
	} catch (err) {
		alert(err);
	}
}

export const buildNewAdoptionApplicationForm  = () => {
	const empty = buildEmptyObject(adoptionApplicationFields);
	empty['image'] = {x: 0.5, y:0.5, scale: 1, rotate: 0, url:'/public/avatar.png', isEmpty: true};
	empty['birthCountry'] = {key: 191, value: 'Vanuatu'}
	return empty;
}

export const loadCivilStatusMtlbAttachment = async (id) => {
	let filter = {and: true};
	filter['civil-status-mtlb-attachment'] = {};
	filter['civil-status-mtlb-attachment']['civilStatusMtlbId'] = id;
	return rest.search('civil-status-mtlb/attachment', filter)
}

export const form2dto = (formData, dto) => {
	dto.mtlbType = MTLB_TYPE_ADOPTION;
	if (!formData.image.isEmpty) {
		let base64Image = formData.image.url;
		let faceMimeType = base64Image.substring(base64Image.indexOf(':') + 1, base64Image.indexOf(';'))
		let base64 = base64Image.substr(base64Image.indexOf(',') + 1);
		dto.face = base64;
		dto.faceMimeType = faceMimeType;
	}
	if (formData.middlename != null) {
		let names = formData.middlename.split(" ");
		dto.secondname = names[0]
		if (names.length > 1)
			dto.thirdname = names[1];
	}
	if (formData.birthCountry)
		dto.birthCountry = formData.birthCountry.key;
	if (formData.birthTime != null && typeof(formData.birthTime) != 'string') {
		const date = new Date(formData.birthTime)
		let birthHour = date.getHours() < 10 ? '0' + date.getHours() : date.getHours();
		let birthMinute = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes();
		dto.birthTime = birthHour + ":" + birthMinute;
	}
	if (formData.otherCitizenshipCsv !== null && formData.otherCitizenshipCsv && Array.isArray(formData.otherCitizenshipCsv)) {
		let otherCitizenshipCsv = formData.otherCitizenshipCsv.join(',');
		dto.otherCitizenshipCsv = otherCitizenshipCsv;
	}
	if (formData.typeOfAcquisition != null)
        dto.typeOfAcquisition = swapObject(TypeOfAcquisition)[formData.typeOfAcquisition]
}


export const dto2form = (response) => {
	let form = response;
	let face = null;
	if (response.face != null) {
		let mimeType = response['faceMimeType'];
		face = "data:".concat(mimeType, ";base64,", response.face)			
	}
	if (response.otherCitizenshipCsv == null || response.otherCitizenshipCsv === "")
  		response.otherCitizenshipCsv = []
	else {
		let values = [];
		let components = response.otherCitizenshipCsv.split(",");
		components.forEach(element => {
			values.push(parseInt(element))
		});
		response.otherCitizenshipCsv = values;
	}
	if (response.birthTime !== null) {
    	response.birthTime = new Date().setHours(response.birthTime[0], response.birthTime[1]);
  	}
	form['image'] = {x: 0.5, y:0.5, scale: 1, rotate: 0, url: (face != null)?face: '/public/avatar.png', isEmpty: (face == null)};
	if (response.motherId == null) {
		if (response.reportedMotherName != null)
  			form.motherInfo = "motherWithoutBirthRecord"
		else if (response.unknownMother != null && response.unknownMother)
			form.motherInfo = "unknownMother"
		else
			form.motherInfo = "motherWithoutBirthRecord"
	} else
		form.motherInfo = "motherWithBirthRecord"

	if (response.fatherId == null) {
		if (response.reportedFatherName != null)
			form.fatherInfo = "fatherWithoutBirthRecord"
		else if (response.unknownFather != null && response.unknownFather)
			form.fatherInfo = "unknownFather"
		else
			form.fatherInfo = "fatherWithoutBirthRecord"
	} else
		form.fatherInfo = "fatherWithBirthRecord"
	if (response.typeOfAcquisition != null)
        form.typeOfAcquisition = TypeOfAcquisition[response.typeOfAcquisition]
	return form;
}

export const newAdoptionApplicationFormForm2Dto = (formData, dto) => {
	dto.vitalRecordId = formData.id;
	dto.id = null;
	if (formData.otherCitizenshipCsv !== null && formData.otherCitizenshipCsv) {
		let otherCitizenshipCsv = formData.otherCitizenshipCsv.join(',');
		dto.otherCitizenshipCsv = otherCitizenshipCsv;
	}
	dto.adoptiveFatherId = null;
	dto.adoptiveMotherId = null;
}