package managedbean.profile;

import java.io.Serializable;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.view.ViewScoped;
import javax.inject.Named;

import TO.FamilyDoctorTO;
import TO.LoggedUserTO;
import TO.PatientTO;
import common.Constants;
import common.UserType;
import managedbean.common.ManagedBeanBase;
import managedbean.common.SessionUtils;

/***
 * ManageBean que gestiona la vista para el cambio de médico de familia para un paciente
 * 
 * @author Marcos García Núñez (mgarcianun@uoc.edu)
 *
 */
@Named("ChangeFD")
@ViewScoped
public class ChangeFamilyDoctorMBean extends ManagedBeanBase implements Serializable {
	private static final long serialVersionUID = 1L;

	private int id;
	private FamilyDoctorTO currentFamilyDoctor;
	private FamilyDoctorTO newFamilyDoctor;
	private List<FamilyDoctorTO> familyDoctorList;
	private String lastUIQuery;

	public ChangeFamilyDoctorMBean() {

	}

	/**
	 * Inicializa el managed Bean
	 * 
	 * Si el usuario logeado es nulo devuelve un error indicando que la sesión actual no es válida.
	 * 
	 * Recupera el id del usuario actual desde la sesión. Dado que solo los pacientes pueden seleccionar un médico de familia, si el usuario es de otro tipo se muestra un mensaje
	 * de error.
	 */
	@PostConstruct
	public void init() {
		// Recuperamos el usuario logeado actual
		LoggedUserTO usr = null;
		this.lastUIQuery = "";
		usr = SessionUtils.getloggedOnUser();

		if (usr == null)
			this.addFacesMessage(FacesMessage.SEVERITY_ERROR, "Sesión no válida", "Su sesión actual no es válida, por favor cierre su sesión y vuelva a logearse en el sistema.");
		else {
			this.id = Integer.valueOf(usr.getId());

			if (usr.getUserType() == UserType.PATIENT) {
				this.familyDoctorList = this.getRemoteManagerCommon().listFamilyDoctorsPaged(0, Constants.MAX_ITEMS_AUTOCOMPLETE_SEARCH);

				PatientTO pat = this.getRemoteManagerCommon().findPatientById(this.id);
				this.currentFamilyDoctor = pat.getFamilyDoctor();
			} else
				this.addFacesMessage(FacesMessage.SEVERITY_ERROR, "Perfil no válido", "Su tipo de usuario no permite que pueda tener acceso a esta página.");
		}
	}

	/**
	 * Devuelve la lista de médicos de familia para el combo de selección.
	 * 
	 * @return Lista de médicos de familia.
	 */
	public List<FamilyDoctorTO> getFamilyDoctorList() {
		return familyDoctorList;
	}

	/**
	 * Método que permite relizar búsqueda de tipo "typeAhead" en la lista de selección de médico.
	 * 
	 * Recibe como parámetro el testo tecleado por el usuario
	 * 
	 * @param query Texto tecleado por el usuario
	 * @return Retorna la lista de médicos de familia coincidentes con el termino buscado.
	 */
	public List<FamilyDoctorTO> completeFamilyDoctor(String query) {
		if (query != null && query.equals(this.lastUIQuery) == false) {
			this.lastUIQuery = query;
			// Recuperamos las primeras ~30 coincidencias, según constante
			this.familyDoctorList = this.getRemoteManagerCommon().listFamilyDoctorsFiltered(query, 0, Constants.MAX_ITEMS_AUTOCOMPLETE_SEARCH);
		}
		return this.familyDoctorList;
	}

	// Id del usuario actual, obtenido de la sessión del usuario logeado.
	public int getId() {
		return id;
	}

	/**
	 * Método que realiza la persistencia del cambio de médico de familia. a través de la invocación al método EJB correspondiente.
	 * 
	 * Se realizan 2 comprobaciones adicionales:
	 * 
	 * 1. Se ha seleccionado un nuevo médico de familia
	 * 
	 * 2. El médico de familia nuevo es diferente al actual
	 * 
	 */
	public void saveData() {
		int error = 0;

		if (this.getNewFamilyDoctor() == null) {
			this.addFacesMessage("frmChangeFD:newFamilyDocAC", FacesMessage.SEVERITY_WARN, "Nuevo médico de familia no seleccionado",
					"Por favor, especifique un nuevvo médico de familia.");
			error++;
		}

		if (this.getCurrentFamilyDoctor() != null && this.getNewFamilyDoctor().getId() == this.getCurrentFamilyDoctor().getId()) {
			this.addFacesMessage("frmChangeFD:newFamilyDocAC", FacesMessage.SEVERITY_WARN, "El médico de familia debe ser diferente",
					"Por favor, seleccione un médico de familia diferente al que tiene actualmente asignado.");
			error++;
		}

		if (error == 0) {
			try {
				PatientTO paTO = this.getRemoteManagerProfile().changeFamilyDoctor(this.getId(), this.newFamilyDoctor.getId());
				this.currentFamilyDoctor = paTO.getFamilyDoctor();
				this.newFamilyDoctor = null;

				this.addFacesMessage(FacesMessage.SEVERITY_INFO, "Los datos se han guardado", "Su médico de familia asignado se ha cambiado correctamente.");
			} catch (Exception e) {
				this.manageException(e);
			}
		}
	}

	public FamilyDoctorTO getCurrentFamilyDoctor() {
		return currentFamilyDoctor;
	}

	public void setCurrentFamilyDoctor(FamilyDoctorTO familyDoctor) {
		this.currentFamilyDoctor = familyDoctor;
	}

	public FamilyDoctorTO getNewFamilyDoctor() {
		return newFamilyDoctor;
	}

	public void setNewFamilyDoctor(FamilyDoctorTO familyDoctor) {
		this.newFamilyDoctor = familyDoctor;
	}

}
