/FileExtraction/Java_unseen/IMS-MAXIMS_openMAXIMS/Source Library/openmaxims_workspace/Pathways/src/ims/pathways/domain/impl/WorklistImpl.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 Daniel Laffan using IMS Development Environment (version 1.60 build 2852.26300)
// Copyright (C) 1995-2007 IMS MAXIMS plc. All rights reserved.

package ims.pathways.domain.impl;

import ims.core.domain.Reports;
import ims.core.domain.impl.ReportsImpl;
import ims.core.vo.lookups.PreActiveActiveInactiveStatus;
import ims.core.vo.lookups.Specialty;
import ims.core.vo.lookups.SpecialtyCollection;
import ims.domain.DomainFactory;
import ims.domain.exceptions.DomainInterfaceException;
import ims.domain.lookups.LookupInstance;
import ims.framework.exceptions.CodingRuntimeException;
import ims.framework.utils.Color;
import ims.framework.utils.Date;
import ims.pathways.configuration.vo.PathwayRefVoCollection;
import ims.pathways.domain.base.impl.BaseWorklistImpl;
import ims.pathways.domain.objects.PatientJourneyTarget;
import ims.pathways.vo.PatientJourneyTargetVoCollection;
import ims.pathways.vo.WorkListTargetCriteriaVo;
import ims.pathways.vo.WorkListTargetCriteriaVoCollection;
import ims.pathways.vo.domain.PathwayLiteVoAssembler;
import ims.pathways.vo.domain.PatientJourneyTargetVoAssembler;
import ims.pathways.vo.domain.TargetConfigurationLiteVoAssembler;
import ims.pathways.vo.lookups.BreachManagement;
import ims.pathways.vo.lookups.PatientTargetStatus;
import ims.vo.interfaces.IMos;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

public class WorklistImpl extends BaseWorklistImpl
{
	private static final long serialVersionUID = 1L;

	/**
	* listSpecialtiesForActivePathways
	*/
	public SpecialtyCollection listSpecialtiesForActivePathways()
	{
		SpecialtyCollection specialtyInstances = new SpecialtyCollection();
		
		List specialties = getDomainFactory().find("select distinct pw.specialty from Pathway as pw where pw.status = :active", new String[] {"active"}, new Object[] {getDomLookup(PreActiveActiveInactiveStatus.ACTIVE)});
		if(specialties != null && specialties.size() > 0)
		{
			Iterator it = specialties.iterator();
			while(it.hasNext())
			{
			    LookupInstance domInst = (LookupInstance) it.next();
			    Specialty lookupInst =  assembleSpecialtyInstance(domInst);
			    specialtyInstances.add(lookupInst);
			}
		}
		
		return specialtyInstances;
	}

	/**
	* listActivePathwaysByCriteria (Specialty and/or Consultant)
	*/
	public ims.pathways.vo.PathwayLiteVoCollection listActivePathwaysBySpecialty(ims.core.vo.lookups.Specialty specialty)
	{
		DomainFactory factory = getDomainFactory();
		StringBuffer hql = new StringBuffer("from Pathway pw where pw.status = :active ");
		
		java.util.ArrayList markers = new java.util.ArrayList();		
		java.util.ArrayList values  = new java.util.ArrayList();
		
		markers.add("active");
		values.add(getDomLookup(PreActiveActiveInactiveStatus.ACTIVE));
	
		if(specialty != null)
		{
			hql.append(" and pw.specialty = :spec");
			markers.add("spec");
			values.add(getDomLookup(specialty));
		}

		List pathways = factory.find(hql.toString(), markers, values);
		return PathwayLiteVoAssembler.createPathwayLiteVoCollectionFromPathway(pathways).sort();
	}

	/**
	* listTargetsForSelectedPathways
	*/
	public ims.pathways.vo.TargetConfigurationLiteVoCollection listTargetsForSelectedPathways(ims.pathways.configuration.vo.PathwayRefVoCollection pathways)
	{
		String hql = "select distinct pt.target from PathwayTarget as pt where (pt.pathway.id in (" + getIdString(pathways) + ") and pt.status = :active)";
		List targets = getDomainFactory().find(hql, new String[] {"active"},new Object[] {getDomLookup(PreActiveActiveInactiveStatus.ACTIVE)});
		return TargetConfigurationLiteVoAssembler.createTargetConfigurationLiteVoCollectionFromTarget(targets);
	}

	private String getIdString(PathwayRefVoCollection pathways)
	{
		String idString = "";
		
		for(int i=0;i<pathways.size();i++)
		{
			idString += pathways.get(i).getID_Pathway();
			idString += ((pathways.size() - (i+1)) > 0 ? "," : "");
		}
		
		return idString;
	}
	
	/**
	 * according to the criteria set the colour of the record -  will be used in the display grid
	 * @param targetConditions 
	 */
	private void setColours(PatientJourneyTargetVoCollection voCollPatJourneyTargets, List targets, WorkListTargetCriteriaVoCollection targetConditions)
	{
		if(voCollPatJourneyTargets == null || targets == null || targetConditions == null)
			throw new CodingRuntimeException("voCollPatJourneyTargets,targets or targetConditions is null in method setColours");
			
		HashMap<Integer,Color> idColourMap = new HashMap<Integer,Color>();
		
		//go through the targets domList and check criteria
		Iterator it = targets.iterator();
		while(it.hasNext())
		{
			PatientJourneyTarget target = (PatientJourneyTarget) it.next();
			idColourMap.put(target.getId(), getColour(target, targetConditions)); 
		}
		
		for(int i=0;i<voCollPatJourneyTargets.size();i++)
		{
			voCollPatJourneyTargets.get(i).setColour(idColourMap.get(voCollPatJourneyTargets.get(i).getID_PatientJourneyTarget()));
		}
	}

	private Color getColour(PatientJourneyTarget target, WorkListTargetCriteriaVoCollection targetConditions)
	{
		java.util.Date today = new Date().getDate();
		java.util.Date uiDate = null;
		
		for(int i=0; i<targetConditions.size(); i++)
		{
			WorkListTargetCriteriaVo item = targetConditions.get(i);
			uiDate = getCriteriaDate(item);
			if(item.getStatusIsNotNull())
			{
				if(item.getStatus().equals(BreachManagement.ACTIVITYBROUGHTFORWARD))
				{
					if(target.getTargetDate().before(today) && target.getCurrentStatus().getStatus().equals(getDomLookup(PatientTargetStatus.EVENTSCHEDULED)) && target.getScheduledDate().after(target.getTargetDate()) && target.getScheduledDate() .after(uiDate))
						return BreachManagement.ACTIVITYBROUGHTFORWARD.getColor();
				}
				else if(item.getStatus().equals(BreachManagement.FUTUREAPPOINTMENTS))
				{
					if(target.getTargetDate().after(today) && target.getCurrentStatus().getStatus().equals(getDomLookup(PatientTargetStatus.EVENTSCHEDULED)) && target.getScheduledDate().after(uiDate))
						return BreachManagement.FUTUREAPPOINTMENTS.getColor();
				}
				else if(item.getStatus().equals(BreachManagement.FUTURETARGETS))
				{
					if(target.getTargetDate().after(today) && target.getCurrentStatus().getStatus().equals(getDomLookup(PatientTargetStatus.INSCOPE)) && (target.getTargetDate().before(uiDate) || target.getTargetDate().equals(uiDate)) )
						return BreachManagement.FUTURETARGETS.getColor();
				}
				else if(item.getStatus().equals(BreachManagement.NOEVENTDETAILS))
				{
					if(target.getTargetDate().before(today) && target.getCurrentStatus().getStatus().equals(getDomLookup(PatientTargetStatus.EVENTSCHEDULED))  && target.getScheduledDate().before(uiDate))
						return BreachManagement.NOEVENTDETAILS.getColor();
				}
				else if(item.getStatus().equals(BreachManagement.NOSCHEDULEDACTIVITY))
				{
					if(target.getTargetDate().before(uiDate) && target.getCurrentStatus().getStatus().equals(getDomLookup(PatientTargetStatus.INSCOPE)))
						return BreachManagement.NOSCHEDULEDACTIVITY.getColor();
				}
				else if(item.getStatus().equals(BreachManagement.TARGETSACHIEVED))
				{
					if(target.getTargetDate().before(today) && target.getCurrentStatus().getStatus().equals(getDomLookup(PatientTargetStatus.TARGETACHIEVED)) && (target.getAchievedDate().before(target.getTargetDate()) || target.getAchievedDate().equals(target.getTargetDate())) && target.getAchievedDate().after(uiDate))
						return BreachManagement.TARGETSACHIEVED.getColor();
				}
				else if(item.getStatus().equals(BreachManagement.TARGETSACHIEVEDOVERTIMELIMIT))
				{
					if(target.getTargetDate().before(today) && target.getCurrentStatus().getStatus().equals(getDomLookup(PatientTargetStatus.TARGETACHIEVED)) && target.getAchievedDate().after(target.getTargetDate()) && target.getAchievedDate().after(uiDate))
						return BreachManagement.TARGETSACHIEVEDOVERTIMELIMIT.getColor();
				}
				else if(item.getStatus().equals(BreachManagement.TARGETSSCHEDULED))
				{
					if(target.getTargetDate().after(today) && target.getCurrentStatus().getStatus().equals(getDomLookup(PatientTargetStatus.EVENTSCHEDULED)) && (target.getScheduledDate().before(target.getTargetDate()) || target.getScheduledDate().equals(target.getTargetDate())) && target.getScheduledDate().before(uiDate))
						return BreachManagement.TARGETSSCHEDULED.getColor();
				}
			}
		}
		
		return Color.Default;
	}

	private ConditionItem createConditionItem(WorkListTargetCriteriaVo item, int i)
	{
		if(item == null)
			throw new CodingRuntimeException("item is null in method createConditionString");
		
		ConditionItem conditionItem = new ConditionItem();
		
		StringBuffer condition = new StringBuffer(" ( ");
		
		if(item.getTargetIsNotNull() && item.getTarget().getID_TargetIsNotNull())
		{
			condition.append(" pjt.pathwayTarget.target.id = :idTarget" + i + " ");
			conditionItem.getMarkers().add("idTarget" + i);
			conditionItem.getValues().add(item.getTarget().getID_Target());
		}
		
		if(item.getStatusIsNotNull())
		{
			if(item.getStatus().equals(BreachManagement.ACTIVITYBROUGHTFORWARD))
			{
				condition.append(" and pjt.targetDate < :today and pjt.currentStatus.status = :scheduled and pjt.scheduledDate > pjt.targetDate and pjt.scheduledDate > :uiDate" + i);
				conditionItem.getMarkers().add("today");
				conditionItem.getMarkers().add("scheduled");
				conditionItem.getMarkers().add("uiDate" + i);
				conditionItem.getValues().add(new Date().getDate());
				conditionItem.getValues().add(getDomLookup(PatientTargetStatus.EVENTSCHEDULED));
				conditionItem.getValues().add(getCriteriaDate(item));
			}
			else if(item.getStatus().equals(BreachManagement.FUTUREAPPOINTMENTS))
			{
				condition.append(" and pjt.targetDate > :today and pjt.currentStatus.status = :scheduled and pjt.scheduledDate > :uiDate" + i);
				conditionItem.getMarkers().add("today");
				conditionItem.getMarkers().add("scheduled");
				conditionItem.getMarkers().add("uiDate" + i);
				conditionItem.getValues().add(new Date().getDate());
				conditionItem.getValues().add(getDomLookup(PatientTargetStatus.EVENTSCHEDULED));
				conditionItem.getValues().add(getCriteriaDate(item));
			}
			else if(item.getStatus().equals(BreachManagement.FUTURETARGETS))
			{
				condition.append(" and pjt.targetDate > :today and pjt.currentStatus.status = :inScope and pjt.targetDate < :uiDate" + i);
				conditionItem.getMarkers().add("today");
				conditionItem.getMarkers().add("inScope");
				conditionItem.getMarkers().add("uiDate" + i);
				conditionItem.getValues().add(new Date().getDate());
				conditionItem.getValues().add(getDomLookup(PatientTargetStatus.INSCOPE));
				conditionItem.getValues().add(getCriteriaDate(item));
			}
			else if(item.getStatus().equals(BreachManagement.NOEVENTDETAILS))
			{
				condition.append(" and pjt.targetDate < :today and pjt.currentStatus.status = :scheduled and pjt.scheduledDate < :uiDate" + i);
				conditionItem.getMarkers().add("today");
				conditionItem.getMarkers().add("scheduled");
				conditionItem.getMarkers().add("uiDate" + i);
				conditionItem.getValues().add(new Date().getDate());
				conditionItem.getValues().add(getDomLookup(PatientTargetStatus.EVENTSCHEDULED));
				conditionItem.getValues().add(getCriteriaDate(item));
			}
			else if(item.getStatus().equals(BreachManagement.NOSCHEDULEDACTIVITY))
			{
				condition.append(" and pjt.targetDate < :uiDate" + i + " and pjt.currentStatus.status = :inScope ");
				conditionItem.getMarkers().add("uiDate" + i);
				conditionItem.getMarkers().add("inScope");
				conditionItem.getValues().add(getCriteriaDate(item));
				conditionItem.getValues().add(getDomLookup(PatientTargetStatus.INSCOPE));
			}
			else if(item.getStatus().equals(BreachManagement.TARGETSACHIEVED))
			{
				condition.append(" and pjt.targetDate < :today and pjt.currentStatus.status = :achieved and pjt.achievedDate <= pjt.targetDate and pjt.achievedDate > :uiDate" + i);
				conditionItem.getMarkers().add("today");
				conditionItem.getMarkers().add("achieved");
				conditionItem.getMarkers().add("uiDate" + i);
				conditionItem.getValues().add(new Date().getDate());
				conditionItem.getValues().add(getDomLookup(PatientTargetStatus.TARGETACHIEVED));
				conditionItem.getValues().add(getCriteriaDate(item));
			}
			else if(item.getStatus().equals(BreachManagement.TARGETSACHIEVEDOVERTIMELIMIT))
			{
				condition.append(" and pjt.targetDate < :today and pjt.currentStatus.status = :achieved and pjt.achievedDate > pjt.targetDate and pjt.achievedDate > :uiDate" + i);
				conditionItem.getMarkers().add("today");
				conditionItem.getMarkers().add("achieved");
				conditionItem.getMarkers().add("uiDate" + i);
				conditionItem.getValues().add(new Date().getDate());
				conditionItem.getValues().add(getDomLookup(PatientTargetStatus.TARGETACHIEVED));
				conditionItem.getValues().add(getCriteriaDate(item));
			}
			else if(item.getStatus().equals(BreachManagement.TARGETSSCHEDULED))
			{
				condition.append(" and pjt.targetDate >= :today and pjt.currentStatus.status = :scheduled and pjt.scheduledDate <= pjt.targetDate and pjt.scheduledDate < :uiDate" + i);
				conditionItem.getMarkers().add("today");
				conditionItem.getMarkers().add("scheduled");
				conditionItem.getMarkers().add("uiDate" + i);
				conditionItem.getValues().add(new Date().getDate());
				conditionItem.getValues().add(getDomLookup(PatientTargetStatus.EVENTSCHEDULED));
				conditionItem.getValues().add(getCriteriaDate(item));
			}
		}
		
		condition.append(" ) ");
		conditionItem.setCondition(condition.toString());
		
		return conditionItem;
	}

	private java.util.Date getCriteriaDate(WorkListTargetCriteriaVo item)
	{
		if(item.getStatus().equals(BreachManagement.ACTIVITYBROUGHTFORWARD))
		{
			return new Date().addDay((item.getNoOfWeeks() * 7)).getDate();
		}
		else if(item.getStatus().equals(BreachManagement.FUTUREAPPOINTMENTS))
		{
			return new Date().addDay((item.getNoOfWeeks() * 7)).getDate();
		}
		else if(item.getStatus().equals(BreachManagement.FUTURETARGETS))
		{
			return new Date().addDay((item.getNoOfWeeks() * 7)).getDate();
		}
		else if(item.getStatus().equals(BreachManagement.NOEVENTDETAILS))
		{
			return new Date().addDay(-(item.getNoOfWeeks() * 7)).getDate();
		}
		else if(item.getStatus().equals(BreachManagement.NOSCHEDULEDACTIVITY))
		{
			return new Date().addDay(-(item.getNoOfWeeks() * 7)).getDate();
		}
		else if(item.getStatus().equals(BreachManagement.TARGETSACHIEVED))
		{
			return new Date().addDay(-(item.getNoOfWeeks() * 7)).getDate();
		}
		else if(item.getStatus().equals(BreachManagement.TARGETSACHIEVEDOVERTIMELIMIT))
		{
			return new Date().addDay(-(item.getNoOfWeeks() * 7)).getDate();
		}
		else if(item.getStatus().equals(BreachManagement.TARGETSSCHEDULED))
		{
			return new Date().addDay((item.getNoOfWeeks() * 7)).getDate();
		}
		
		throw new CodingRuntimeException("Code should never reach here");
	}

	private Specialty assembleSpecialtyInstance(LookupInstance domInst)
	{
		if(domInst == null)
			throw new CodingRuntimeException("domInst is null in method assembleSpecialtyInstance");
		
		ims.framework.utils.ImagePath img = null;
		ims.framework.utils.Color color = null;		
		img = null;
		if (domInst.getImage() != null) 
		{
			img = new ims.framework.utils.ImagePath(domInst.getImage().getImageId(), domInst.getImage().getImagePath());
		}
		color = domInst.getColor();
		if (color != null) 
			color.getValue();
		
		Specialty inst = new Specialty(domInst.getId(),domInst.getText(), domInst.isActive(), null, img, color);
		
		return inst;
	}
	
	private class ConditionItem
	{
		private ArrayList markers = new ArrayList();
		private ArrayList values = new ArrayList();
		private String condition = "";
		
		public ConditionItem()
		{
			
		}

		public String getCondition()
		{
			return condition;
		}

		public void setCondition(String condition)
		{
			this.condition = condition;
		}

		public ArrayList getMarkers()
		{
			return markers;
		}

		public ArrayList getValues()
		{
			return values;
		}	
	}

	public String[] getReportAndTemplate(Integer nReportId, Integer nTemplateId) throws DomainInterfaceException
	{
		Reports impl = (Reports) getDomainImpl(ReportsImpl.class);
		return impl.getReportAndTemplate(nReportId, nTemplateId);
	}

	public PatientJourneyTargetVoCollection listPatientJourneyTargetsByCriteria(PathwayRefVoCollection pathways, WorkListTargetCriteriaVoCollection targetConditions, IMos consultant) 
	{
		StringBuffer hql = new StringBuffer("from PatientJourneyTarget pjt where  pjt.pathwayJourney.pathway.id in (" + getIdString(pathways) + ")");
		
		ArrayList markers = new ArrayList();
		ArrayList values = new ArrayList();
		
		if(targetConditions != null)
		{
			hql.append(" and (( ");
			for(int i=0;i<targetConditions.size();i++)
			{
				WorkListTargetCriteriaVo criteriaItem = targetConditions.get(i);
				ConditionItem condtionItem = createConditionItem(criteriaItem, i);
				hql.append(condtionItem.getCondition());
				hql.append((targetConditions.size() - (i+1)) > 0 ? " or " : "");
				markers.addAll(condtionItem.getMarkers());
				values.addAll(condtionItem.getValues());
			}
			hql.append(" ) ");
		}
		
		hql.append(" ) ");
		
		//WDEV-9946
		if(consultant != null && consultant.getIMosHcpId() != null)
		{
			hql.append(" and pjt.pathwayJourney.responsibleConsultant.id = :idConsultant ");
			markers.add("idConsultant");
			values.add(consultant.getIMosHcpId());//WDEV-9946
		}

		hql.append(" order by pjt.pathwayTarget.target.id, pjt.targetDate, pjt.achievedDate");
		
		List jTargets =  getDomainFactory().find(hql.toString(), markers, values);
		PatientJourneyTargetVoCollection voCollPatJourneyTargets = null;
		if(jTargets != null && jTargets.size() > 0)
			voCollPatJourneyTargets = PatientJourneyTargetVoAssembler.createPatientJourneyTargetVoCollectionFromPatientJourneyTarget(jTargets);
	
		if(voCollPatJourneyTargets != null)
			setColours(voCollPatJourneyTargets, jTargets, targetConditions);
		
		return voCollPatJourneyTargets;
	}
}
