/*
 * 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.modules.requests;

import hu.astrid.debgen.authentication.domain.DebGenUser;
import hu.astrid.debgen.patientmanagement.domain.Patient;
import hu.astrid.debgen.patientmanagement.domain.modules.requests.AnalysisRequest;
import hu.astrid.debgen.patientmanagement.domain.modules.requests.LabelList;
import hu.astrid.debgen.patientmanagement.domain.sample.Sample;
import hu.astrid.debgen.patientmanagement.service.modules.PrintManagerService;
import hu.astrid.debgen.patientmanagement.service.modules.requests.RequestManagerService;
import hu.astrid.debgen.patientmanagement.service.sample.SampleManagerService;
import hu.astrid.toucan.control.persistence.DatabaseServiceClass;
import org.apache.log4j.Logger;
import org.hibernate.Hibernate;
import org.hibernate.Session;

import java.net.URI;
import java.util.List;
import java.util.Locale;

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

    
    // <editor-fold defaultstate="collapsed" desc="Request">
    /**
     * Starts a session, and creates or modifies the given requests DB record
     * @param request The new request datas
     * @throws Exception When DB fails
     */
    public void createOrModifyRequest(AnalysisRequest request) throws Exception {
        Session session = null;
        try {
            session = startSession();
            session.beginTransaction();
            RequestManagerService service = getRequestService(session);
            SampleManagerService sms = (SampleManagerService) SampleManagerService.getInstance(session);
//            PatientManagerService ps = getService(session);
            for (Sample s : request.getSamples()) {
                sms.create(s);
            }
            service.create(request);
//            ps.create(request.getPatient());
            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 AnalysisRequest loadRequest(Long id) throws Exception {
        Session session = null;
        try {
            session = startSession();
            session.beginTransaction();
            RequestManagerService service = getRequestService(session);
            AnalysisRequest requestCommon = service.load(id);
            Hibernate.initialize(requestCommon.getPatient().getAnalysisRequests());
            session.getTransaction().commit();
            return requestCommon;
        } 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 deleteRequest(Long id) throws Exception {
        Session session = null;
        try {
            session = startSession();
            session.beginTransaction();
            RequestManagerService service = getRequestService(session);
            AnalysisRequest req = service.load(id);
            service.delete(req);
            session.getTransaction().commit();
        } catch (Exception ex) {
            rollback();
            throw ex;
        } finally {
            closeSession();
        }
    }

    /**
     * Returns a list of requests
     * @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
     * @return The list of records on the current page.
     * @throws Exception When DB fails.
     */
    public List<AnalysisRequest> listRequests(String order, int pageNumber, int pageSize) throws Exception {
        Session session = null;
        try {
            session = startSession();
            session.beginTransaction();
            RequestManagerService service = getRequestService(session);
            List<AnalysisRequest> found = service.list(order, pageNumber * pageSize, pageSize);
            session.getTransaction().commit();
            return found;
        } catch (Exception ex) {
            rollback();
            throw ex;
        } finally {
            closeSession();
        }
    }

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

    /**
     * Returns the number of result pages when listing requests
     * @param size The number of elements on one page
     * @return The number of the pages
     * @throws Exception When DB fails.
     */
    public int getNumberOfListPages(int size) throws Exception {
        Session session = null;
        try {
            session = startSession();
            session.beginTransaction();
            RequestManagerService service = getRequestService(session);
            double found = service.countList();
            session.getTransaction().commit();
            return (int) ((found - 0.01) / size);
        } catch (Exception ex) {
            rollback();
            throw ex;
        } finally {
            closeSession();
        }
    }

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

    // <editor-fold defaultstate="collapsed" desc="PDF">
    public List<URI> generatePDF(LabelList labelList, AnalysisRequest analysis, DebGenUser user, int copies) throws Exception {
        try{
        Patient patient = analysis.getPatient();
        if (patient.isNamed() && !user.isDataRecorder()) {
            patient.setPatientType(1);
        }
        patient.setCopies(copies);
        analysis.setPatient(patient);
        analysis.setLabels(labelList);
        return (PrintManagerService.getInstance().generatePdfFromAnalysis(analysis, new Locale(user.getLanguageCode())));
        } catch (Exception e) {
            Logger.getLogger(this.getClass()).error(e.getMessage(), e);
            throw e;
        }
    }// </editor-fold>
}
