package ejb.common;

import java.util.ArrayList;
import java.util.List;

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;

import TO.FamilyDoctorTO;
import TO.MedicalSpecialtyTO;
import TO.MedicalTestTO;
import TO.PatientTO;
import TO.PrimaryHealthCareCenterTO;
import TO.QuestionTO;
import TO.SpecialistDoctorTO;
import TO.SystemAdminTO;
import TO.VisitTO;
import common.Utils;
import jpa.FamilyDoctorJPA;
import jpa.MedicalSpecialtyJPA;
import jpa.MedicalTestJPA;
import jpa.PatientJPA;
import jpa.PrimaryHealthCareCenterJPA;
import jpa.QuestionJPA;
import jpa.SpecialistDoctorJPA;
import jpa.SystemAdminJPA;
import jpa.VisitJPA;

/***
 * 
 * @author Marcos García Núñez (mgarcianun@uoc.edu)
 *
 */
@Stateless
public class CommonFacadeBean implements CommonFacadeRemote, CommonFacadeLocal {
	// Persistence Unit Context
	@PersistenceContext(unitName = "MyHealth")
	private EntityManager entman;

	/**
	 * Metodo que devuelve todas las especialidades medicas registradas en el
	 * sistema
	 * 
	 * @return Devuelve una Lista de MedicalSpecialtyTO (Transfer Objects).
	 */
	public List<MedicalSpecialtyTO> listAllMedicalSpecialties() {
		return this.listMedicalSpecialtiesPaged(0, 0);
	}

	/**
	 * Metodo que devuelve las especialidades médicas de forma paginada
	 * 
	 * Acepta como parametro la página (comenzando en 0) y el número de elementos de
	 * cada página.
	 * 
	 * si pageSize == 0, entonces se devuelven todas las especialidades registradas
	 * (Se ignora el parámetro).
	 * 
	 * @return Devuelve una Lista de MedicalSpecialtyTO (Transfer Objects).
	 */
	public List<MedicalSpecialtyTO> listMedicalSpecialtiesPaged(int pageNumber, int pageSize) {
		return listMedicalSpecialtiesFiltered(null, pageNumber, pageSize);
	}

	/**
	 * Método que devuelve una lista de espcialidades médicas que tienen una
	 * coincidencia parcial en el nombre o en la descripción con el termino de
	 * búsqueda (searchTerm) especificado.
	 * 
	 * Además permite la paginacción de datos. Si pageSize == 0 no se realiza
	 * paginación y se devuelven todos los resultados.
	 * 
	 * Si serachTerm es nulo o cadena vacía entonces no se tiene en cuenta el
	 * parámetro y devuelven todas las especialidades existentes.
	 * 
	 * @return Devuelve una Lista de MedicalSpecialtyTO (Transfer Objects).
	 */
	public List<MedicalSpecialtyTO> listMedicalSpecialtiesFiltered(String searchTerm, int pageNumber, int pageSize) {
		String strQuery = "SELECT ms from MedicalSpecialtyJPA ms %s order by ms.name, ms.description";
		String strFilter = "";
		if (searchTerm == null)
			searchTerm = "";
		else
			searchTerm = Utils.normalizeTerm(searchTerm);

		if (searchTerm.length() > 0) {
			strFilter = "WHERE lower(ms.name) LIKE :searchTerm OR lower(ms.description) LIKE :searchTerm";
		}

		TypedQuery<MedicalSpecialtyJPA> query = entman.createQuery(String.format(strQuery, strFilter),
				MedicalSpecialtyJPA.class);

		if (searchTerm.length() > 0)
			query.setParameter("searchTerm", "%" + searchTerm + "%");

		if (pageSize > 0) {
			query.setFirstResult(pageNumber * pageSize);
			query.setMaxResults(pageSize);
		}

		List<MedicalSpecialtyJPA> allJPA = query.getResultList();
		List<MedicalSpecialtyTO> allSpecialities = new ArrayList<MedicalSpecialtyTO>();

		for (MedicalSpecialtyJPA item : allJPA) {
			allSpecialities.add(this.getPOJOforMedicalSpecialtyJPA(item));
		}

		return allSpecialities;
	}

	/**
	 * Método que devuelve todos los CAPs registrados en el sistema
	 * 
	 * @return Devuelve una Lista de MedicalSpecialtyTO (Transfer Objects).
	 */
	public List<PrimaryHealthCareCenterTO> listAllCAPs() {
		return this.listCAPsPaged(0, 0);
	}

	/**
	 * Método que devuelve una lista de CAPs (Centros de Atención Primarios) de
	 * forma paginada
	 * 
	 * Si pageSize == 0 no se realiza paginación y se devuelven todos los
	 * resultados.
	 * 
	 * @return Devuelve una Lista de MedicalSpecialtyTO (Transfer Objects).
	 */
	public List<PrimaryHealthCareCenterTO> listCAPsPaged(int pageNumber, int pageSize) {
		return this.listCAPsFiltered(null, pageNumber, pageSize);
	}

	/**
	 * Método que devuelve una lista de CAPs (Centros de Atención Primarios) que
	 * tienen una coincidencia parcial en el nombre o en la localización con el
	 * termino de búsqueda (searchTerm) especificado.
	 * 
	 * Además permite la paginacción de datos. Si pageSize == 0 no se realiza
	 * paginación y se devuelven todos los resultados.
	 * 
	 * Si serachTerm es nulo o cadena vacía entonces no se tiene en cuenta el
	 * parámetro y devuelven todos los CAPs existentes.
	 * 
	 * @return Devuelve una Lista de PrimaryHealthCareCenterTO (Transfer Objects).
	 */
	public List<PrimaryHealthCareCenterTO> listCAPsFiltered(String searchTerm, int pageNumber, int pageSize) {
		String strQuery = "SELECT phc from PrimaryHealthCareCenterJPA phc %s order by phc.name, phc.location";
		String strFilter = "";
		if (searchTerm == null)
			searchTerm = "";
		else
			searchTerm = Utils.normalizeTerm(searchTerm);

		if (searchTerm.length() > 0) {
			strFilter = "WHERE lower(phc.name) LIKE :searchTerm OR lower(phc.location) LIKE :searchTerm";
		}

		TypedQuery<PrimaryHealthCareCenterJPA> query = entman.createQuery(String.format(strQuery, strFilter),
				PrimaryHealthCareCenterJPA.class);

		if (searchTerm.length() > 0)
			query.setParameter("searchTerm", "%" + searchTerm + "%");

		if (pageSize > 0) {
			query.setFirstResult(pageNumber * pageSize);
			query.setMaxResults(pageSize);
		}

		List<PrimaryHealthCareCenterJPA> allJPA = query.getResultList();
		List<PrimaryHealthCareCenterTO> allCAPs = new ArrayList<PrimaryHealthCareCenterTO>();

		for (PrimaryHealthCareCenterJPA item : allJPA) {
			allCAPs.add(this.getPOJOforPrimaryHealthCareCenterJPA(item));
		}

		return allCAPs;
	}

	/**
	 * Método que devuelve una lista con todos los médicos de familia registrados en
	 * el sistema.
	 * 
	 * @return Devuelve una Lista de FamilyDoctorTO (Transfer Objects).
	 */
	public List<FamilyDoctorTO> listAllFamilyDoctors() {
		return this.listFamilyDoctorsPaged(0, 0);
	}

	/**
	 * Método que devuelve una lista con todos los médicos de familia registrados en
	 * el sistema de forma paginada.
	 * 
	 * Si pageSize == 0 no se realiza paginación y se devuelven todos los
	 * resultados.
	 * 
	 * @return Devuelve una Lista de FamilyDoctorTO (Transfer Objects).
	 */
	public List<FamilyDoctorTO> listFamilyDoctorsPaged(int pageNumber, int pageSize) {
		return this.listFamilyDoctorsFiltered(null, pageNumber, pageSize);
	}

	/**
	 * Método que devuelve una lista de médicos de familia que tienen una
	 * coincidencia parcial en el nombre o en los apellidos con el termino de
	 * búsqueda (searchTerm) especificado.
	 * 
	 * Además permite la paginacción de datos. Si pageSize == 0 no se realiza
	 * paginación y se devuelven todos los resultados.
	 * 
	 * Si serachTerm es nulo o cadena vacía entonces no se tiene en cuenta el
	 * parámetro y devuelven todos los registros existentes.
	 * 
	 * @return Devuelve una Lista de FamilyDoctorTO (Transfer Objects).
	 */
	public List<FamilyDoctorTO> listFamilyDoctorsFiltered(String searchTerm, int pageNumber, int pageSize) {
		String strQuery = "SELECT fd FROM FamilyDoctorJPA fd %s order by fd.name, fd.surname";
		String strFilter = "";
		if (searchTerm == null)
			searchTerm = "";
		else
			searchTerm = Utils.normalizeTerm(searchTerm);

		if (searchTerm.length() > 0) {
			strFilter = "WHERE lower(fd.name) LIKE :searchTerm OR lower(fd.surname) LIKE :searchTerm";
		}

		TypedQuery<FamilyDoctorJPA> query = entman.createQuery(String.format(strQuery, strFilter),
				FamilyDoctorJPA.class);

		if (searchTerm.length() > 0)
			query.setParameter("searchTerm", "%" + searchTerm + "%");

		if (pageSize > 0) {
			query.setFirstResult(pageNumber * pageSize);
			query.setMaxResults(pageSize);
		}

		List<FamilyDoctorJPA> allFDsJPA = query.getResultList();
		List<FamilyDoctorTO> allFDTOs = new ArrayList<FamilyDoctorTO>();

		for (FamilyDoctorJPA item : allFDsJPA) {
			allFDTOs.add(this.getPOJOforFamilyDoctorJPA(item, 0));
		}

		return allFDTOs;
	}
	
	/**
	 * Método que devuelve una lista con todos los pacientes registrados en el sistema de forma paginada.
	 * 
	 * Si pageSize == 0 no se realiza paginación y se devuelven todos los resultados.
	 * 
	 * @return Devuelve una Lista de PatientTO (Transfer Objects).
	 */
	public List<PatientTO> listPatientsPaged(int pageNumber, int pageSize) {
		return this.listPatientsFiltered(null, pageNumber, pageSize);
	}
	
	/**
	 * Método que devuelve una lista de pacientes que tienen una coincidencia parcial en el nombre o en los apellidos con el termino de búsqueda (searchTerm) especificado.
	 * 
	 * Además permite la paginacción de datos. Si pageSize == 0 no se realiza paginación y se devuelven todos los resultados.
	 * 
	 * Si serachTerm es nulo o cadena vacía entonces no se tiene en cuenta el parámetro y devuelven todos los registros existentes.
	 * 
	 * @return Devuelve una Lista de PatientTO (Transfer Objects).
	 */
	public List<PatientTO> listPatientsFiltered(String searchTerm, int pageNumber, int pageSize) {
		String strQuery = "SELECT p FROM PatientJPA p %s order by p.name, p.surname";
		String strFilter = "";
		if (searchTerm == null)
			searchTerm = "";
		else
			searchTerm = Utils.normalizeTerm(searchTerm);

		if (searchTerm.length() > 0) {
			strFilter = "WHERE lower(p.name) LIKE :searchTerm OR lower(p.surname) LIKE :searchTerm";
		}

		TypedQuery<PatientJPA> query = entman.createQuery(String.format(strQuery, strFilter), PatientJPA.class);

		if (searchTerm.length() > 0)
			query.setParameter("searchTerm", "%" + searchTerm + "%");

		if (pageSize > 0) {
			query.setFirstResult(pageNumber * pageSize);
			query.setMaxResults(pageSize);
		}

		List<PatientJPA> allPAsJPA = query.getResultList();
		List<PatientTO> allPATOs = new ArrayList<PatientTO>();

		for (PatientJPA item : allPAsJPA) {
			allPATOs.add(this.getPOJOforPatientJPA(item, 0));
		}

		return allPATOs;
	}

	/**
	 * Método que convierte un objecto de tipo MedicalSpecialtyJPA (JPA) a su
	 * equivalente MedicalSpecialtyTO (Tranfer Object)
	 * 
	 * @return MedicalSpecialtyTO (Transfer Object de una especialidad médica)
	 */
	public MedicalSpecialtyTO getPOJOforMedicalSpecialtyJPA(MedicalSpecialtyJPA ms) {
		MedicalSpecialtyTO msTO = null;

		if (ms != null) {
			msTO = new MedicalSpecialtyTO(ms.getId(), ms.getName(), ms.getDescription());
		}

		return msTO;
	}

	/**
	 * Método que convierte un objecto de tipo PrimaryHealthCareCenterJPA (JPA) a su
	 * equivalente PrimaryHealthCareCenterTO (Tranfer Object)
	 * 
	 * @return PrimaryHealthCareCenterTO (Transfer Object de un CAP)
	 */
	public PrimaryHealthCareCenterTO getPOJOforPrimaryHealthCareCenterJPA(PrimaryHealthCareCenterJPA phc) {
		PrimaryHealthCareCenterTO phcTO = null;

		if (phc != null) {
			phcTO = new PrimaryHealthCareCenterTO(phc.getId(), phc.getName(), phc.getLocation());
		}

		return phcTO;
	}

	/**
	 * Método que convierte un objecto de tipo SpecialistDoctorJPA (JPA) a su
	 * equivalente SpecialistDoctorTO (Tranfer Object)
	 * 
	 * El parámetro nestedProps es un valor entero que indica a que nivel de
	 * profundidad se debe navegar a través de las propiedades relacionadas para
	 * convertirlas de JPA a TO. Un valor 0 indica que no se convertirá ninguna
	 * propiedad que tenga un entidad JPA relacionada (tendrá valor null en el
	 * objeto TO).
	 * 
	 * @return SpecialistDoctorTO (Transfer Object de un médico especialista)
	 */
	public SpecialistDoctorTO getPOJOforSpecialistDoctorJPA(SpecialistDoctorJPA sd, int nestedProps) {
		SpecialistDoctorTO sdTO = null;

		if (sd != null) {
			MedicalSpecialtyJPA ms = null;
			if (nestedProps > 0)
				ms = sd.getMedicalSpecialty();

			nestedProps--;
			sdTO = new SpecialistDoctorTO(sd.getId(), sd.getProfessionalNumber(), sd.getNif(), sd.getName(),
					sd.getSurname(), sd.getPassword(), sd.getEmail(), this.getPOJOforMedicalSpecialtyJPA(ms));
		}

		return sdTO;
	}

	/**
	 * Método que convierte un objecto de tipo FamilyDoctorJPA (JPA) a su
	 * equivalente FamilyDoctorTO (Tranfer Object)
	 *
	 * El parámetro nestedProps es un valor entero que indica a que nivel de
	 * profundidad se debe navegar a través de las propiedades relacionadas para
	 * convertirlas de JPA a TO. Un valor 0 indica que no se convertirá ninguna
	 * propiedad que tenga un entidad JPA relacionada (tendrá valor null en el
	 * objeto TO).
	 * 
	 * @return FamilyDoctorTO (Transfer Object de un médico especialista)
	 */
	public FamilyDoctorTO getPOJOforFamilyDoctorJPA(FamilyDoctorJPA fd, int nestedProps) {
		FamilyDoctorTO fdTO = null;

		if (fd != null) {
			PrimaryHealthCareCenterJPA phc = null;
			if (nestedProps > 0)
				phc = fd.getPrimaryHealthCareCenter();

			nestedProps--;
			fdTO = new FamilyDoctorTO(fd.getId(), fd.getProfessionalNumber(), fd.getNif(), fd.getName(),
					fd.getSurname(), fd.getPassword(), fd.getEmail(), this.getPOJOforPrimaryHealthCareCenterJPA(phc));
		}

		return fdTO;
	}

	/**
	 * Método que convierte un objecto de tipo PatientJPA (JPA) a su equivalente
	 * PatientTO (Tranfer Object)
	 * 
	 * El parámetro nestedProps es un valor entero que indica a que nivel de
	 * profundidad se debe navegar a través de las propiedades relacionadas para
	 * convertirlas de JPA a TO. Un valor 0 indica que no se convertirá ninguna
	 * propiedad que tenga un entidad JPA relacionada (tendrá valor null en el
	 * objeto TO).
	 * 
	 * @return PatientTO (Transfer Object de un médico especialista)
	 */
	public PatientTO getPOJOforPatientJPA(PatientJPA pat, int nestedProps) {
		PatientTO paTO = null;

		if (pat != null) {
			FamilyDoctorJPA fd = null;
			if (nestedProps > 0)
				fd = pat.getFamilyDoctor();

			nestedProps--;
			paTO = new PatientTO(pat.getId(), pat.getPersonalIdentificationCode(), pat.getNif(), pat.getName(),
					pat.getSurname(), pat.getPassword(), pat.getEmail(),
					this.getPOJOforFamilyDoctorJPA(fd, nestedProps));
		}

		return paTO;
	}

	/**
	 * Método que recupera un paciente a partir de su Identificador (Id) de base de
	 * datos.
	 * 
	 * @return PatientTO (Transfer Object del objeto recuperado) o null si no se
	 *         encuentra el objeto buscado
	 */
	public PatientTO findPatientById(int patientId) {
		// Recuperamos propiedades anidadas 1 nivel!
		return this.getPOJOforPatientJPA(entman.find(PatientJPA.class, patientId), 1);
	}

	/**
	 * Método que recupera un paciente a partir de su CIP (Código de Identificación
	 * de Paciente)
	 * 
	 * @return PatientTO (Transfer Object del objeto recuperado) o null si no se
	 *         encuentra el objeto buscado
	 */
	public PatientTO findPatientByCode(String code) {
		TypedQuery<PatientJPA> query = entman
				.createQuery("from PatientJPA pat where pat.personalIdentificationCode=:code", PatientJPA.class);
		query.setMaxResults(1);
		query.setParameter("code", code);

		List<PatientJPA> results = query.getResultList();
		if (results.size() > 0)
			return this.getPOJOforPatientJPA(results.get(0), 1);
		else
			return null;
	}

	/**
	 * Método que recupera un paciente a partir de su NIF
	 * 
	 * @return PatientTO (Transfer Object del objeto recuperado) o null si no se
	 *         encuentra el objeto buscado
	 */
	public PatientTO findPatientByNif(String searchedNIF) {
		TypedQuery<PatientJPA> query = entman.createQuery("from PatientJPA pat where pat.nif=:nif", PatientJPA.class);
		query.setMaxResults(1);
		query.setParameter("nif", searchedNIF);

		List<PatientJPA> results = query.getResultList();
		if (results.size() > 0)
			return this.getPOJOforPatientJPA(results.get(0), 1);
		else
			return null;
	}

	/**
	 * Método que recupera un médico de familia a partir de su Identificador (Id) de
	 * base de datos.
	 * 
	 * @return FamilyDoctorTO (Transfer Object del objeto recuperado) o null si no
	 *         se encuentra el objeto buscado
	 */
	public FamilyDoctorTO findFamilyDoctorById(int ProfessionalNumberId) {
		return this.getPOJOforFamilyDoctorJPA(entman.find(FamilyDoctorJPA.class, ProfessionalNumberId), 1);
	}

	/**
	 * Método que recupera un médico de familia a partir de su NP (Número de
	 * profesional)
	 * 
	 * @return FamilyDoctorTO (Transfer Object del objeto recuperado) o null si no
	 *         se encuentra el objeto buscado
	 */
	public FamilyDoctorTO findFamilyDoctorByCode(String code) {
		TypedQuery<FamilyDoctorJPA> query = entman
				.createQuery("from FamilyDoctorJPA d where d.professionalNumber=:code", FamilyDoctorJPA.class);

		query.setParameter("code", code);

		List<FamilyDoctorJPA> results = query.getResultList();
		if (results.size() > 0)
			return this.getPOJOforFamilyDoctorJPA(results.get(0), 1);
		else
			return null;
	}

	/**
	 * Método que recupera un médico de familia a partir de su NIF
	 * 
	 * @return FamilyDoctorTO (Transfer Object del objeto recuperado) o null si no
	 *         se encuentra el objeto buscado
	 */
	public FamilyDoctorTO findFamilyDoctorByNif(String searchedNIF) {
		TypedQuery<FamilyDoctorJPA> query = entman.createQuery("from FamilyDoctorJPA d where d.nif=:nif",
				FamilyDoctorJPA.class);
		query.setMaxResults(1);
		query.setParameter("nif", searchedNIF);

		List<FamilyDoctorJPA> results = query.getResultList();
		if (results.size() > 0)
			return this.getPOJOforFamilyDoctorJPA(results.get(0), 1);
		else
			return null;
	}

	/**
	 * Método que recupera un médico especialista a partir de su Identificador (Id)
	 * de base de datos.
	 * 
	 * @return SpecialistDoctorTO (Transfer Object del objeto recuperado) o null si
	 *         no se encuentra el objeto buscado
	 */
	public SpecialistDoctorTO findSpecialistDoctorById(int ProfessionalNumberId) {
		return this.getPOJOforSpecialistDoctorJPA(entman.find(SpecialistDoctorJPA.class, ProfessionalNumberId), 1);
	}

	/**
	 * Método que recupera un médico especialista a partir de su NP (Número de
	 * profesional)
	 * 
	 * @return SpecialistDoctorTO (Transfer Object del objeto recuperado) o null si
	 *         no se encuentra el objeto buscado
	 */
	public SpecialistDoctorTO findSpecialistDoctorByCode(String code) {
		TypedQuery<SpecialistDoctorJPA> query = entman
				.createQuery("from SpecialistDoctorJPA d where d.professionalNumber=:code", SpecialistDoctorJPA.class);

		query.setParameter("code", code);

		List<SpecialistDoctorJPA> results = query.getResultList();
		if (results.size() > 0)
			return this.getPOJOforSpecialistDoctorJPA(results.get(0), 1);
		else
			return null;
	}

	/**
	 * Método que recupera un médico especialista a partir de su NIF
	 * 
	 * @return SpecialistDoctorTO (Transfer Object del objeto recuperado) o null si el objeto JPA es nulo
	 */
	public SpecialistDoctorTO findSpecialistDoctorByNif(String searchedNIF) {
		TypedQuery<SpecialistDoctorJPA> query = entman.createQuery("from SpecialistDoctorJPA d where d.nif=:nif",
				SpecialistDoctorJPA.class);
		query.setMaxResults(1);
		query.setParameter("nif", searchedNIF);

		List<SpecialistDoctorJPA> results = query.getResultList();
		if (results.size() > 0)
			return this.getPOJOforSpecialistDoctorJPA(results.get(0), 1);
		else
			return null;
	}

	/**
	 * Método que convierte un objecto de tipo QuestionJPA (JPA) a su equivalente
	 * QuestionTO (Tranfer Object)
	 *
	 * El parámetro nestedProps es un valor entero que indica a que nivel de profundidad se debe navegar a través de las propiedades relacionadas para convertirlas de JPA a TO. Un
	 * valor 0 indica que no se convertirá ninguna propiedad que tenga un entidad JPA relacionada (tendrá valor null en el objeto TO).
	 * 
	 * @return QuestionTO (Transfer Object del objeto recuperado) o null si el objeto JPA es nulo
	 */
	public QuestionTO getPOJOforQuestionJPA(QuestionJPA qs, int nestedProps) {
		QuestionTO qsTO = null;

		if (qs != null) {
			FamilyDoctorJPA fd = null;
			PatientJPA pat = null;
			if (nestedProps > 0) {
				fd = qs.getFamilyDoctor();
				pat = qs.getPatient();
			}

			nestedProps--;
			qsTO = new QuestionTO(qs.getId(), qs.getTitle(), qs.getMessage(), qs.getStatus(),
					this.getPOJOforPatientJPA(pat, nestedProps), this.getPOJOforFamilyDoctorJPA(fd, nestedProps),
					qs.getResponse());
		}

		return qsTO;
	}

	/**
	 * Método que converite un objeto de tipo VisitJPA a su equivalente VisitTO (Transfer Object)
	 * 
	 * El parámetro nestedProps es un valor entero que indica a que nivel de profundidad se debe navegar a través de las propiedades relacionadas para convertirlas de JPA a TO. Un
	 * valor 0 indica que no se convertirá ninguna propiedad que tenga un entidad JPA relacionada (tendrá valor null en el objeto TO).
	 * 
	 * @return VisitTO (Transfer Object del objeto recuperado) o null si el objeto JPA es nulo
	 */
	public VisitTO getPOJOforVisitJPA(VisitJPA vi, int nestedProps) {
		VisitTO qsTO = null;

		if (vi != null) {
			FamilyDoctorJPA fd = null;
			PatientJPA pat = null;
			if (nestedProps > 0) {
				fd = vi.getFamilyDoctor();
				pat = vi.getPatient();
			}

			nestedProps--;
			qsTO = new VisitTO(vi.getId(), vi.getDate(), vi.getTime(), vi.getObservations(), vi.getResult(),
					this.getPOJOforFamilyDoctorJPA(fd, nestedProps), this.getPOJOforPatientJPA(pat, nestedProps));
		}

		return qsTO;
	}

	public MedicalTestTO getPOJOforMedicalTestJPA(MedicalTestJPA mt, int nestedProps) {
		MedicalTestTO qsTO = null;

		if (mt != null) {
			SpecialistDoctorJPA fd = null;
			PatientJPA pat = null;
			if (nestedProps > 0) {
				fd = mt.getSpecialistDoctor();
				pat = mt.getPatient();
			}

			nestedProps--;
			qsTO = new MedicalTestTO(mt.getId(), mt.getDate(), mt.getTime(), mt.getObservations(), mt.getHighresimage(), mt.getType(),
					this.getPOJOforPatientJPA(pat, nestedProps), this.getPOJOforSpecialistDoctorJPA(fd, nestedProps));
		}

		return qsTO;
	}

	@Override
	public SystemAdminTO getPOJOforSystemAdminJPA(SystemAdminJPA admin) {
		SystemAdminTO adminTO = null;

		if (admin != null) {
			adminTO = new SystemAdminTO(admin.getEmail(), admin.getPassword());
		}

		return adminTO;
	}
}
