/FileExtraction/Java_unseen/IMS-MAXIMS_openMAXIMS/Source Library/openmaxims_workspace/Pathways/src/ims/pathways/domain/impl/PatientJourneyImpl.java
//#############################################################################
//#                                                                           #
//#  Copyright (C) <2015>  <IMS MAXIMS>                                       #
//#                                                                           #
//#  This program is free software: you can redistribute it and/or modify     #
//#  it under the terms of the GNU Affero General Public License as           #
//#  published by the Free Software Foundation, either version 3 of the       #
//#  License, or (at your option) any later version.                          # 
//#                                                                           #
//#  This program is distributed in the hope that it will be useful,          #
//#  but WITHOUT ANY WARRANTY; without even the implied warranty of           #
//#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            #
//#  GNU Affero General Public License for more details.                      #
//#                                                                           #
//#  You should have received a copy of the GNU Affero General Public License #
//#  along with this program.  If not, see <http://www.gnu.org/licenses/>.    #
//#                                                                           #
//#  IMS MAXIMS provides absolutely NO GUARANTEE OF THE CLINICAL SAFTEY of    #
//#  this program.  Users of this software do so entirely at their own risk.  #
//#  IMS MAXIMS only ensures the Clinical Safety of unaltered run-time        #
//#  software that it builds, deploys and maintains.                          #
//#                                                                           #
//#############################################################################
//#EOH
// This code was generated by Marius Mihalec using IMS Development Environment (version 1.60 build 2838.16667)
// Copyright (C) 1995-2007 IMS MAXIMS plc. All rights reserved.

package ims.pathways.domain.impl;

import ims.admin.domain.ClinicAdmin;
import ims.admin.domain.impl.ClinicAdminImpl;
import ims.RefMan.domain.objects.CatsReferral;
import ims.RefMan.vo.CatsReferralForJourneyVo;
import ims.RefMan.vo.domain.CatsReferralForJourneyVoAssembler;
import ims.configuration.gen.ConfigFlag;
import ims.core.admin.domain.objects.Referral;
import ims.core.admin.vo.ReferralRefVo;
import ims.core.clinical.domain.objects.ReferralLetterDetails;
import ims.core.patient.vo.PatientRefVo;
import ims.core.vo.ClinicVo;
import ims.core.vo.ReferralLiteVo;
import ims.core.vo.ReferralLiteVoCollection;
import ims.core.vo.domain.ReferralLiteVoAssembler;
import ims.core.vo.lookups.SourceOfReferral;
import ims.core.vo.lookups.TaxonomyType;
import ims.domain.DomainFactory;
import ims.domain.exceptions.DomainInterfaceException;
import ims.domain.exceptions.DomainRuntimeException;
import ims.domain.exceptions.StaleObjectException;
import ims.framework.enumerations.SystemLogLevel;
import ims.framework.enumerations.SystemLogType;
import ims.framework.exceptions.CodingRuntimeException;
import ims.framework.utils.Date;
import ims.pathways.configuration.domain.objects.Pathway;
import ims.pathways.configuration.vo.PathwayRefVo;
import ims.pathways.configuration.vo.TargetRefVo;
import ims.pathways.domain.HL7PathwayIf;
import ims.pathways.domain.base.impl.BasePatientJourneyImpl;
import ims.pathways.domain.objects.PathwayClock;
import ims.pathways.domain.objects.PatientJourneyBreach;
import ims.pathways.domain.objects.PatientJourneyTarget;
import ims.pathways.domain.objects.PatientPathwayJourney;
import ims.pathways.vo.PathwayCurrentClockForRttStatusVo;
import ims.pathways.vo.PathwayLiteVo;
import ims.pathways.vo.PatientJourneyBreachReasonListVo;
import ims.pathways.vo.PatientJourneyCommentsVo;
import ims.pathways.vo.PatientJourneyInterfaceVo;
import ims.pathways.vo.PatientJourneyJourneyTargetInterfaceVo;
import ims.pathways.vo.PatientJourneyShortVoCollection;
import ims.pathways.vo.PatientJourneyTargetRefVo;
import ims.pathways.vo.PatientJourneyTargetVo;
import ims.pathways.vo.PatientJourneyTargetVoCollection;
import ims.pathways.vo.PatientJourneyVoCollection;
import ims.pathways.vo.PatientPathwayJourneyRefVo;
import ims.pathways.vo.PauseDetailsVo;
import ims.pathways.vo.PauseDetailsVoCollection;
import ims.pathways.vo.domain.PathwayCurrentClockForRttStatusVoAssembler;
import ims.pathways.vo.domain.PathwayLiteVoAssembler;
import ims.pathways.vo.domain.PatientJourneyBreachReasonListVoAssembler;
import ims.pathways.vo.domain.PatientJourneyCommentsVoAssembler;
import ims.pathways.vo.domain.PatientJourneyEventInterfaceVoAssembler;
import ims.pathways.vo.domain.PatientJourneyInterfaceVoAssembler;
import ims.pathways.vo.domain.PatientJourneyJourneyTargetInterfaceVoAssembler;
import ims.pathways.vo.domain.PatientJourneyShortVoAssembler;
import ims.pathways.vo.domain.PatientJourneyTargetInterfaceVoAssembler;
import ims.pathways.vo.domain.PatientJourneyTargetVoAssembler;
import ims.pathways.vo.domain.PatientJourneyVoAssembler;
import ims.pathways.vo.domain.PauseDetailsVoAssembler;

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

public class PatientJourneyImpl extends BasePatientJourneyImpl
{
	private static final long serialVersionUID = 1L;

	/**
	* Lists all referrals for a patient
	*/
	public ims.core.vo.ReferralLiteVoCollection listReferrals(ims.core.patient.vo.PatientRefVo patient)
	{		
		if(patient == null)
			throw new DomainRuntimeException("Invalid patient");
		
		DomainFactory factory = getDomainFactory();
		return ReferralLiteVoAssembler.createReferralLiteVoCollectionFromReferral(factory.find("from Referral rf where rf.patient.id = " + patient.getID_Patient()));
	}
	public PatientJourneyShortVoCollection listPatientJourneyShortByReferral(ReferralRefVo referral) 
	{
		if(referral == null)
			throw new DomainRuntimeException("Invalid referral");
		
		DomainFactory factory = getDomainFactory();
		
		ArrayList<String> markers = new ArrayList<String>();
		markers.add("referral");
		ArrayList<Object> values = new ArrayList<Object>();
		values.add(referral.getID_Referral());
		//WDEV-21176  exclude RIE
		return PatientJourneyShortVoAssembler.createPatientJourneyShortVoCollectionFromPatientPathwayJourney((factory.find("from PatientPathwayJourney pj where (pj.isRIE is null OR pj.isRIE = 0) and pj.referral.id = :referral", markers, values)));		
	}	
	
	public PatientJourneyShortVoCollection listPatientJourneyShortByPathway(PathwayRefVo voRef) 
	{
		if(voRef == null)
			throw new DomainRuntimeException("Invalid pathway");
		
		DomainFactory factory = getDomainFactory();
		
		ArrayList<String> markers = new ArrayList<String>();
		markers.add("pathway");
		ArrayList<Object> values = new ArrayList<Object>();
		values.add(voRef.getID_Pathway());
		
		return PatientJourneyShortVoAssembler.createPatientJourneyShortVoCollectionFromPatientPathwayJourney((factory.find("from PatientPathwayJourney pj where pj.pathway.id = :pathway", markers, values)));		
	}	
	
	public PatientJourneyVoCollection listPatientJourney(ReferralRefVo referral) 
	{
		if(referral == null)
			throw new DomainRuntimeException("Invalid referral");
		
		DomainFactory factory = getDomainFactory();
		
		ArrayList<String> markers = new ArrayList<String>();
		markers.add("referral");
		ArrayList<Object> values = new ArrayList<Object>();
		values.add(referral.getID_Referral());
		
		return PatientJourneyVoAssembler.createPatientJourneyVoCollectionFromPatientPathwayJourney((factory.find("from PatientPathwayJourney pj where pj.referral.id = :referral", markers, values)));		
	}
	
	public PatientJourneyInterfaceVo getPatientJourney(PatientPathwayJourneyRefVo profile, PathwayRefVo pathway) 
	{
		if(profile == null)
			throw new DomainRuntimeException("Invalid profile");
		
		DomainFactory factory = getDomainFactory();
				
 		PatientJourneyInterfaceVo vo = PatientJourneyInterfaceVoAssembler.create((PatientPathwayJourney)factory.getDomainObject(profile));
		
 		if(vo == null)
 			throw new DomainRuntimeException("Profile not found");
 		
		vo.setJourneyEvents(PatientJourneyEventInterfaceVoAssembler.createPatientJourneyEventInterfaceVoCollectionFromPatientEvent(factory.find("from PatientEvent pe where pe.journey.id = " + profile.getID_PatientPathwayJourney() + " order by pe.eventDateTime, pe.id",ConfigFlag.UI.MAX_NO_OF_PATIENT_JOURNEY_EVENTS_LISTED.getValue()))); //wdev-12567
 		vo.setPathwayTargets(PatientJourneyTargetInterfaceVoAssembler.createPatientJourneyTargetInterfaceVoCollectionFromPatientJourneyTarget( listCurrentPathwayJourneyTargets(factory, profile, pathway != null ? pathway : vo.getPathway())));
		return vo;
	}
	private List listCurrentPathwayJourneyTargets(DomainFactory factory, PatientPathwayJourneyRefVo profile, PathwayRefVo pathway)
	{
		return factory.find(" from PatientJourneyTarget pt where pt.journeyClock = pt.pathwayJourney.currentClock and pt.pathwayJourney.id = " + profile.getID_PatientPathwayJourney() + " and pt.pathwayTarget.pathway.id = " +  pathway.getID_Pathway());
	}	
	
	public PathwayLiteVo getPathwayLite(PathwayRefVo voRef)
	{
		if (voRef.getID_Pathway() == null)
			throw new CodingRuntimeException("No id provided for Pathway");

		return PathwayLiteVoAssembler.create((Pathway) getDomainFactory().getDomainObject(voRef));
	}
	public PatientJourneyTargetVo getPatientJourneyTarget(PatientJourneyTargetRefVo journeyTarget)
	{
		return PatientJourneyTargetVoAssembler.create( (PatientJourneyTarget) getDomainFactory().getDomainObject(journeyTarget));
	}
	public PatientJourneyTargetVoCollection listCurrentPathwayJourneyTargets(PatientPathwayJourneyRefVo journey, PathwayRefVo pathway)
	{
		return PatientJourneyTargetVoAssembler.createPatientJourneyTargetVoCollectionFromPatientJourneyTarget(listCurrentPathwayJourneyTargets( getDomainFactory(), journey, pathway));
	}
	
	public ReferralLiteVo getReferralByJourney(PatientPathwayJourneyRefVo journey)
	{
		DomainFactory factory = getDomainFactory();
		
		String hql = "select pj.referral from PatientPathwayJourney as pj left join pj.referral as referral " + 
				"where (pj.id = " + journey.getID_PatientPathwayJourney() + " )";
		
		List referralList = factory.find(hql);
		if(referralList != null && referralList.size() == 1)
			return ReferralLiteVoAssembler.create((Referral) referralList.get(0));
		
		return null;
	}
	
	public void save(PatientJourneyJourneyTargetInterfaceVo record) throws StaleObjectException
	{	
		if(!record.isValidated())
			throw new CodingRuntimeException("Record not validated");
		
		DomainFactory factory = getDomainFactory();
		PatientJourneyTarget domainRecord = PatientJourneyJourneyTargetInterfaceVoAssembler.extractPatientJourneyTarget(factory, record);		
		factory.save(domainRecord);
	}
	
	public PatientJourneyCommentsVo getPatientPathwayJourney(PatientPathwayJourneyRefVo voRef)
	{
		if (voRef.getID_PatientPathwayJourney() == null)
			throw new CodingRuntimeException("No id provided for Patient Journey");

		return PatientJourneyCommentsVoAssembler.create((PatientPathwayJourney) getDomainFactory().getDomainObject(voRef));
	}
	
	public String getClinicName(String clinicCode)
	{
		if (clinicCode == null)
			return null;
		
		ClinicAdmin newImpl = (ClinicAdmin) getDomainImpl(ClinicAdminImpl.class);
		ClinicVo clinic = newImpl.getClinicByPASCode(clinicCode);
		if (clinic != null)
			return clinic.getClinicName();
		return null;
	}
	//wdev-14124
	public ReferralLiteVoCollection listReferralWithPathways(PatientRefVo patient) 
	{
		
		if(patient == null)
			throw new DomainRuntimeException("Invalid patient");
		
		ReferralLiteVoCollection referralColl = new ReferralLiteVoCollection();
		
		DomainFactory factory = getDomainFactory();
		 
		ArrayList<String> marques = new ArrayList<String>();
		ArrayList<Object> values = new ArrayList<Object>();

		String query = " select catsRef, p1_1.referral from CatsReferral as catsRef,  PatientPathwayJourney as p1_1 join p1_1.referral as r1_1 where p1_1.patient.id =:id  and catsRef.journey.id = p1_1.id ";
		marques.add("id");
		values.add(patient.getID_Patient());
		
		List<?> list =  factory.find(query, marques, values);

		for (int i = 0; list != null && i < list.size(); i++)
		{
			if (list.get(i) instanceof Object[])
			{
				Object[] result = (Object[]) list.get(i);
				CatsReferralForJourneyVo catsReferral = null;
				ReferralLiteVo referral = null;
				
				if (result[0] instanceof CatsReferral)
				{
					catsReferral = CatsReferralForJourneyVoAssembler.create((CatsReferral) result[0]);
				}
				
				if (result[1] instanceof Referral)
				{
					referral = ReferralLiteVoAssembler.create((Referral) result[1]);
				}
				
				if (catsReferral != null && referral != null)
				{
					referral.setCatsReferralDetails(catsReferral);
				}
				
				referralColl.add(referral);
			}
			
		}
				
		return referralColl;
	}
	
	public ReferralLiteVo getReferralFromSelectedCatsReferral(Integer catsReferralID)
	{
		if (catsReferralID == null)
			return null;
		DomainFactory factory = getDomainFactory();		
		 
		ArrayList<String> marques = new ArrayList<String>();
		ArrayList<Object> values = new ArrayList<Object>();
		marques.add("id");
		values.add(catsReferralID);	
	
		String query = " select referral from CatsReferral as catsReferral left join catsReferral.journey as referralJourney left join referralJourney.referral as referral where catsReferral.id = :id ";
		List<?> referral = factory.find(query, marques, values);
		
		if(referral != null && referral.size() > 0 && referral.get(0) instanceof Referral)
			return ReferralLiteVoAssembler.create((Referral) referral.get(0));
		
		return null;
	}

	/**
	* WDEV-18474
         * saveCancerPathway
         */
	public void saveCancerPathway(PatientPathwayJourneyRefVo journey, Date cancerPathwayDate) throws StaleObjectException
	{
		if (journey == null || cancerPathwayDate == null)
			return;
	
		DomainFactory factory = getDomainFactory();
		
		PatientPathwayJourney domJourney = (PatientPathwayJourney)factory.getDomainObject(PatientPathwayJourney.class, journey.getID_PatientPathwayJourney());
		domJourney.setIsCancerPathway(true);
		domJourney.setCancerPathwayDate(cancerPathwayDate.getDate());
		factory.save(domJourney);
		
		// We now need to  check the referral type for the associated CatsReferral.  If it is GP, then we want the 62 day target in scope
		ArrayList<String> labels = new ArrayList<String>();
		ArrayList<Object> values = new ArrayList<Object>();
		labels.add("journey");
		values.add(domJourney);	
		String query = " select cat.referralDetails from CatsReferral cat where cat.journey = :journey ";
		
		List<?> referralDetails = factory.find(query, labels, values);
		if (referralDetails != null && referralDetails.size() > 0)
		{
			// There should be just one!
			ReferralLetterDetails domRefLetter = (ReferralLetterDetails) referralDetails.get(0);
			if (domRefLetter != null && domRefLetter.getReferrerType() != null &&
					domRefLetter.getReferrerType().getId() == SourceOfReferral.GP.getId())
			{
				// Find the Target 62Day
				HL7PathwayIf hl7Impl = (HL7PathwayIf) getDomainImpl(HL7PathwayIfImpl.class);
				try 
				{
					TargetRefVo target = hl7Impl.getTargetByTaxonomyMap(TaxonomyType.PAS, "62D");
					hl7Impl.bringTargetIntoScopeWithoutEvent(target, journey, cancerPathwayDate);
					
				}
				catch (DomainInterfaceException e) 
				{
					super.createSystemLogEntry(SystemLogType.APPLICATION, SystemLogLevel.WARNING, e.getMessage());
					return;
				}
			}		
		}
	}
	
	public Date getRTTBreachDate(ReferralRefVo referral)
	{
		if(referral == null || referral.getID_Referral() == null)
			return null;
		
		DomainFactory factory = getDomainFactory();
		
		String query = "select rd.end18WW from CatsReferral as cr left join cr.referralDetails as rd left join cr.journey as j left join j.referral as r where r.id = :ReferralId";
		List<?> dates = factory.find(query, new String[] {"ReferralId"}, new Object[] {referral.getID_Referral()});
		
		if(dates != null && dates.size() > 0)
		{
			if(dates.get(0) instanceof java.util.Date)
				return new Date((java.util.Date) dates.get(0));
		}
		
		return null;
	}
	
	public Integer getCurrentPauseDetails(ReferralRefVo ref)
	{
		if(ref == null || ref.getID_Referral() == null)
			return 0;
		
		DomainFactory factory = getDomainFactory();		
		
		String query = "select cc from CatsReferral as cr left join cr.referralDetails as rd left join cr.journey as j left join j.currentClock as cc left join j.referral as r where r.id = :ReferralId";
		List<?> pauseDetails = factory.find(query, new String[] {"ReferralId"}, new Object[] {ref.getID_Referral()});
		
		if (pauseDetails != null && pauseDetails.size() > 0 && pauseDetails.get(0) != null && pauseDetails.get(0) instanceof PathwayClock)
		{
			PauseDetailsVoCollection pauseDetColl = PauseDetailsVoAssembler.createPauseDetailsVoCollectionFromPauseDetails(((PathwayClock) pauseDetails.get(0)).getPauseDetails());
			if (pauseDetColl != null && pauseDetColl.size() > 0)
			{
				int nrOfDays = 0;
				for (int i = 0; i < pauseDetColl.size(); i++)
				{	
					PauseDetailsVo pauseDet = pauseDetColl.get(i);
					if (pauseDet.getActive() && pauseDet.getPauseStartIsNotNull() && pauseDet.getPauseStopIsNotNull() && pauseDet.getPauseStart().isLessThan(pauseDet.getPauseStop()))
						nrOfDays = nrOfDays + (int) Date.daysBetween(pauseDet.getPauseStart(), pauseDet.getPauseStop());
				}
			
				return nrOfDays;
			}
		}
		
		return 0;
	}
	
	//WDEV-19936 
	public PathwayCurrentClockForRttStatusVo getRTTStatus(Integer referralID)
	{
		if (referralID == null)
			return null;
		
		DomainFactory factory = getDomainFactory();		
		 
		ArrayList<String> marques = new ArrayList<String>();
		ArrayList<Object> values = new ArrayList<Object>();

		String query = " select currentClock from PatientPathwayJourney as patientPathwayJourney left join patientPathwayJourney.referral as pathReferral left join patientPathwayJourney.currentClock as currentClock where pathReferral.id = :id ";
		marques.add("id");
		values.add(referralID);	
		
		List<?> list = factory.find(query, marques, values);
	
		if (list != null && list.size() > 0)
			return PathwayCurrentClockForRttStatusVoAssembler.create((PathwayClock) list.get(0));
		
		return null;
	}
	
	//WDEV-19849
	public Boolean getHasAtLeastOneActiveBreachReason(Integer patientJourneyID)
	{
		DomainFactory factory = getDomainFactory();

		if (patientJourneyID == null)
		{
			return false;
		}

		StringBuffer hql = new StringBuffer();

		hql.append(" select count(breachReason.id) from PatientPathwayJourney as PatientPathwayJourney left join PatientPathwayJourney.patientJourneyBreachReason as breachReason where (breachReason.isRIE is null or breachReason.isRIE = 0) and PatientPathwayJourney.id = :journeyID ");

		 Object[] count = factory.find(hql.toString(), new String[] { "journeyID" }, new Object[] {patientJourneyID}).toArray();
		
		 if(count != null && count.length > 0)
			 if (((Long) count[0]).intValue() > 0) 
			 return true;
		
		
		return false;
	}

	// WDEV-20385
	public PatientJourneyBreachReasonListVo getBreachReasons(PatientPathwayJourneyRefVo commentRef) 
	{
		if (commentRef == null)
			return null;
		
		DomainFactory factory = getDomainFactory();
		
		ArrayList<String> markers = new ArrayList<String>();
		ArrayList<Object> values = new ArrayList<Object>();

		String hql = "select reason from PatientPathwayJourney as journey left join journey.patientJourneyBreachReason as reason where journey.id = :journeyID and (reason.isRIE is null OR reason.isRIE = 0) order by reason.breachReasonDate desc";

		markers.add("journeyID");
		values.add(commentRef.getID_PatientPathwayJourney());

		return PatientJourneyBreachReasonListVoAssembler.create((PatientJourneyBreach) factory.findFirst(hql, markers, values));
	}	
}
