/*
 * This file is part of DebGen Biobank Software developed by ASTRID Research.
 * All rights reserved. Reproduction, modification, use or disclosure
 * to third parties without express authority is forbidden.
 *
 * Copyright ASTRID Research Inc., Hungary, 2009-2011.
 *
 * ASTRID Research
 * Headquaters: Csapo utca 42. Debrecen H-4029 HUNGARY
 * Phone: +36-52-533-173        Fax: +36-52-533-174
 * Web: http://www.astrid.hu    E-mail: info@astrid.hu
 *
 * Project name: DebGen Biobank Software project.
 * URLS:
 * Developers: Istvan Zoltan Nagy (istvan.nagy@astrid.hu)
 */
package hu.astrid.debgen.patientmanagement.facade;

import hu.astrid.debgen.patientmanagement.domain.AnonymousData;
import hu.astrid.debgen.patientmanagement.service.PatientCodeGeneratorService;
import hu.astrid.debgen.patientmanagement.service.PatientManagerService;
import hu.astrid.debgen.patientmanagement.domain.Patient;
import hu.astrid.debgen.patientmanagement.domain.PersonalIdentity;
import hu.astrid.toucan.control.persistence.DatabaseServiceClass;
import java.util.List;
import org.hibernate.Session;

/**
 * The facade, which is handling the patients
 * @author inagy
 */
public class PatientManagerFacade extends DatabaseServiceClass {

    // <editor-fold defaultstate="collapsed" desc="Patient">
    /**
     * Starts a session, and creates or modifies the given patients DB record
     * @param patient The new patient datas
     * @param oldId The old personalId object if it should be deleted
     * @param oldAn The old anonymousData object if it should be deleted
     * @throws Exception When DB fails
     */
    public void createOrModifyPatient(Patient patient, PersonalIdentity oldId, AnonymousData oldAn) throws Exception {
        Session session = null;
        try {
            session = startSession();
            session.beginTransaction();
            boolean newPatient = (patient.getId() == null);
            PatientManagerService service = getService(session);
            service.create(patient);
            if (oldAn != null) {
                service.delete(oldAn);
            }
            if (oldId != null) {
                service.delete(oldId);
            }
            if (newPatient) {
                PatientCodeGeneratorService.removeFromFresh(patient.getPatientCode());
            }
            session.getTransaction().commit();
        } catch (Exception ex) {
            rollback();
            throw ex;
        } finally {
            closeSession();
        }
    }

    /**
     * Loads the request by the given id
     * @param id The id of the request
     * @return The request object with the specified id (if there is such thing)
     * @throws Exception When DB fails
     */
    public Patient loadPatient(Long id) throws Exception {
        Session session = null;
        try {
            session = startSession();
            session.beginTransaction();
            PatientManagerService service = getService(session);
            Patient patient = service.load(id);
            session.getTransaction().commit();
            return patient;
        } catch (Exception ex) {
            rollback();
            throw ex;
        } finally {
            closeSession();
        }
    }

    /**
     * Deletes the request by the given id
     * @param id The id of the request
     * @throws Exception When DB fails
     */
    public void deletePatient(Long id) throws Exception {
        Session session = null;
        try {
            session = startSession();
            session.beginTransaction();
            PatientManagerService service = getService(session);
            Patient patient = service.load(id);
            service.delete(patient);
            session.getTransaction().commit();
        } catch (Exception ex) {
            rollback();
            throw ex;
        } finally {
            closeSession();
        }
    }

    /**
     * Finds the matching anonymous request(s) using the criterias
     * @param what The search criterias
     * @param order The ordering attribute to order the results ascending
     * @param pageNumber The number of the requested page.
     * @param pageSize The number of elements on one page
     * @param asc Order ascending
     * @return The list of records on the current page.
     * @throws Exception When DB fails.
     */
    public List<Patient> findPatients(Patient what, String order, int pageNumber, int pageSize, boolean asc) throws Exception {
        Session session = null;
        try {
            session = startSession();
            session.beginTransaction();
            PatientManagerService service = getService(session);
            List<Patient> found = service.find(what, order, pageNumber * pageSize, pageSize, asc);
            session.getTransaction().commit();
            return found;
        } catch (Exception ex) {
            rollback();
            throw ex;
        } finally {
            closeSession();
        }
    }

    /**
     * Returns a list of anonymous patients
     * @param order The ordering attribute to order the results ascending
     * @param pageNumber The number of the requested page.
     * @param pageSize The number of elements on one page
     * @param asc Order ascending
     * @return The list of records on the current page.
     * @throws Exception When DB fails.
     */
    public List<Patient> listPatients(String order, int pageNumber, int pageSize, boolean asc) throws Exception {
        Session session = null;
        try {
            session = startSession();
            session.beginTransaction();
            PatientManagerService service = getService(session);
            List<Patient> found = service.list(order, pageNumber * pageSize, pageSize, asc);
            session.getTransaction().commit();
            return found;
        } catch (Exception ex) {
            rollback();
            throw ex;
        } finally {
            closeSession();
        }
    }

    /**
     * Finds all the matching request(s) (named and/or anonymous) using the criterias
     * @param what The search criterias
     * @param order The ordering attribute to order the results ascending
     * @param pageNumber The number of the requested page.
     * @param pageSize The number of elements on one page
     * @param asc Order ascending
     * @return The list of records on the current page.
     * @throws Exception When DB fails.
     */
    public List<Patient> findAllPatients(Patient what, String order, int pageNumber, int pageSize, boolean asc) throws Exception {
        Session session = null;
        try {
            session = startSession();
            session.beginTransaction();
            PatientManagerService service = getService(session);
            List<Patient> found = service.findAll(what, order, pageNumber * pageSize, pageSize, asc);
            session.getTransaction().commit();
            return found;
        } catch (Exception ex) {
            rollback();
            throw ex;
        } finally {
            closeSession();
        }
    }

    /**
     * Returns a list of anonymous and/or named patients
     * @param order The ordering attribute to order the results ascending
     * @param pageNumber The number of the requested page.
     * @param pageSize The number of elements on one page
     * @param asc Order ascending
     * @return The list of records on the current page.
     * @throws Exception When DB fails.
     */
    public List<Patient> listAllPatients(String order, int pageNumber, int pageSize, boolean asc) throws Exception {
        Session session = null;
        try {
            session = startSession();
            session.beginTransaction();
            PatientManagerService service = getService(session);
            List<Patient> found = service.listAll(order, pageNumber * pageSize, pageSize, asc);
            session.getTransaction().commit();
            return found;
        } catch (Exception ex) {
            rollback();
            throw ex;
        } finally {
            closeSession();
        }
    }

    /**
     * Gets a new PatientManagerService using a Session
     * @param session The session
     * @return the new service
     */
    private PatientManagerService getService(Session session) {
        PatientManagerService service = (PatientManagerService) PatientManagerService.getInstance(session);
        return service;
    }

    /**
     * Returns the number of result pages when listing patients
     * @param size The number of elements on one page
     * @param all The answer of the "Search all of patients (anonymous and/or named)?" question
     * @return The number of the pages
     * @throws Exception When DB fails.
     */
    public int getNumberOfListPages(int size, boolean all) throws Exception {
        Session session = null;
        try {
            session = startSession();
            session.beginTransaction();
            PatientManagerService service = getService(session);
            double found = service.countList(all);
            session.getTransaction().commit();
            return (int) ((found - 0.01) / size);
        } catch (Exception ex) {
            rollback();
            throw ex;
        } finally {
            closeSession();
        }
    }

    /**
     * Returns the number of result pages matching the given criterias
     * @param size The number of elements on one page
     * @param all The answer of the "Search all of patients (anonymous and/or named)?" question
     * @return The number of result pages
     * @throws Exception When DB fails.
     */
    public int getNumberOfSearchPages(Patient patient, int size, boolean all) throws Exception {
        Session session = null;
        try {
            session = startSession();
            session.beginTransaction();
            PatientManagerService service = getService(session);
            double found = service.countSearchList(patient, all);
            session.getTransaction().commit();
            return (int) ((found - 0.01) / size);
        } catch (Exception ex) {
            rollback();
            throw ex;
        } finally {
            closeSession();
        }
    }

    /**
     * Lists the names of patients matching the pattern
     * @param pattern The pattern that should occure somewhere in the name of the request
     * @return The list of matching request names
     * @throws Exception When DB fails...
     */
    public List<String> listNames(String pattern) throws Exception {
        Session session = null;
        try {
            session = startSession();
            session.beginTransaction();
            PatientManagerService service = getService(session);
            List<String> result = service.listNames(pattern);
            session.getTransaction().commit();
            return result;
        } catch (Exception ex) {
            rollback();
            throw ex;
        } finally {
            closeSession();
        }
    }

    /**
     * Lists the TAJ numbers of patients matching the pattern
     * @param pattern The pattern that should occure somewhere in the TAJ of the request
     * @return The list of matching request TAJ numbers
     * @throws Exception When DB fails...
     */
    public List<String> listTAJ(String pattern) throws Exception {
        Session session = null;
        try {
            session = startSession();
            session.beginTransaction();
            PatientManagerService service = getService(session);
            List<String> result = service.listTAJ(pattern);
            session.getTransaction().commit();
            return result;
        } catch (Exception ex) {
            rollback();
            throw ex;
        } finally {
            closeSession();
        }
    }

    /**
     * Lists the BiobankCodes of patients matching the pattern
     * @param pattern The pattern that should occure somewhere in the code of the request
     * @param all The answer of the "Search all of patients (anonymous and/or named)?" question
     * @return The list of matching request BiobankCodes
     * @throws Exception When DB fails...
     */
    public List<String> listCode(String pattern, boolean all) throws Exception {
        Session session = null;
        try {
            session = startSession();
            session.beginTransaction();
            PatientManagerService service = getService(session);
            List<String> result = service.listCode(pattern, all);
            session.getTransaction().commit();
            return result;
        } catch (Exception ex) {
            rollback();
            throw ex;
        } finally {
            closeSession();
        }
    }

    /**
     * Generates a brand new request BiobankCode to use it for a new request
     * @return A request code, which is free
     * @throws Exception When the generation process isn't possible
     */
    public String getPatientCode() throws Exception {
        return PatientCodeGeneratorService.generateCode();
    }

    /**
     * Lists the list of start matching values of the Patient's "field" attribute
     * @param field The Name of an attribute in the request relation
     * @param query The pattern witch should be found
     * @return The list of results
     * @throws Exception When DB fails
     */
    public List<String> listField(String field, String query) throws Exception {
        Session session = null;
        try {
            session = startSession();
            session.beginTransaction();
            PatientManagerService service = getService(session);
            List<String> result = service.listField(field, query);
            session.getTransaction().commit();
            return result;
        } catch (Exception ex) {
            rollback();
            throw ex;
        } finally {
            closeSession();
        }
    }

    /**
     * Finds a person by taj
     * @param taj The TAJ of the patient
     * @return The patient object with the matching TAJ
     * @throws Exception When the DB fails or the Person is missing
     */
    public Patient findByTaj(String taj) throws Exception {
        Session session = null;
        try {
            session = startSession();
            session.beginTransaction();
            PatientManagerService service = getService(session);
            Patient found = service.findByTaj(taj);
            session.getTransaction().commit();
            return found;
        } catch (Exception ex) {
            rollback();
            throw ex;
        } finally {
            closeSession();
        }
    }

    /**
     * Finds a person by name
     * @param name The Name of the patient
     * @return The patient object with the matching Name
     * @throws Exception When the DB fails or the Person is missing
     */
    public String findByName(String name) throws Exception {
        Session session = null;
        try {
            session = startSession();
            session.beginTransaction();
            PatientManagerService service = getService(session);
            String found = service.findByName(name);
            session.getTransaction().commit();
            return found;
        } catch (Exception ex) {
            rollback();
            throw ex;
        } finally {
            closeSession();
        }
    }// </editor-fold>

}
