/FileExtraction/Java_unseen/IMS-MAXIMS_openMAXIMS/Source Library/openmaxims_workspace/Nursing/src/ims/nursing/forms/metric/Logic.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 Calin Perebiceanu using IMS Development Environment (version 1.80 build 3987.30129)
// Copyright (C) 1995-2010 IMS MAXIMS. All rights reserved.

package ims.nursing.forms.metric;

import ims.configuration.gen.ConfigFlag;
import ims.core.vo.VSMetrics;
import ims.core.vo.VSMetricsCollection;
import ims.domain.exceptions.StaleObjectException;
import ims.framework.MessageButtons;
import ims.framework.MessageIcon;
import ims.framework.enumerations.FormMode;
import ims.framework.enumerations.SortOrder;
import ims.framework.exceptions.FormOpenException;
import ims.framework.exceptions.PresentationLogicException;
import ims.framework.utils.DateTime;
import ims.framework.utils.graphing.GraphingMetrics;
import ims.framework.utils.graphing.GraphingPoint;
import ims.nursing.forms.metric.GenForm.GroupHEnumeration;
import ims.nursing.forms.metric.GenForm.GroupWEnumeration;
import ims.nursing.forms.metric.GenForm.grdMetricsRow;
import ims.nursing.vo.LastHeightMetricRecordVo;
import ims.nursing.vo.MetricSearchCriteriaVo;

import java.util.ArrayList;
import java.util.Comparator;

public class Logic extends BaseLogic
{
	private static final long serialVersionUID = 1L;
	
	@Override
	protected void onFormOpen(Object[] args) throws ims.framework.exceptions.PresentationLogicException
	{
		initialize();
		
		//WDEV-19389 
		if (!(form.getGlobalContext().Core.getPatientShortIsNotNull() && form.getGlobalContext().Nursing.getMetricSearchCriteriaIsNotNull() && form.getGlobalContext().Nursing.getMetricSearchCriteria().getPatientIsNotNull() && form.getGlobalContext().Core.getPatientShort().equals(form.getGlobalContext().Nursing.getMetricSearchCriteria().getPatient())))
			form.getGlobalContext().Nursing.setMetricSearchCriteria(null);
		
		if(form.getGlobalContext().Nursing.getMetricSearchCriteriaIsNotNull())
		{
			setSearchCriteria(form.getGlobalContext().Nursing.getMetricSearchCriteria());
		}
		//WDEV-19389 - end
		
		open();
	}

	@Override
	protected void onFormModeChanged()
	{
		updateControlsState();
	}

	@Override
	protected void onImbClearClick() throws PresentationLogicException
	{
		clear();
		clearSearch();
		updateControlsState();
		form.getGlobalContext().Nursing.setMetricSearchCriteria(null);
	}

	@Override
	protected void onImbSearchClick() throws PresentationLogicException
	{
		search(true);
		updateControlsState();

	}
	

	@Override
	protected void onBtnNewClick() throws PresentationLogicException
	{
		newInstance();

	}

	@Override
	protected void onBtnEditClick() throws PresentationLogicException
	{
		updateInstance();

	}

	@Override
	protected void onBtnSaveClick() throws PresentationLogicException
	{
		populateBMIandSurface();
		if (save())
		{
			open(false);
		}
			
	}

	@Override
	protected void onBtnCancelClick() throws PresentationLogicException
	{
		form.getLocalContext().setSelectedInstance(form.grdMetrics().getValue());
		//WDEV-11654 
		open(true);
	}
	@Override
	protected void onDecWeightValueChanged() throws PresentationLogicException
	{
		populateBMIandSurface();
		
	}

	private void populateBMIandSurface()
	{
		form.decBMI().setValue(bodyMassIndex(form.decHeight().getValue(),form.decWeight().getValue()));
		form.decSurface().setValue(bodySurfaceArea(form.decHeight().getValue(),form.decWeight().getValue()));
	}

	@Override
	protected void onDecHeightValueChanged() throws PresentationLogicException
	{
		populateBMIandSurface();
		
	}

	@Override
	protected void onGrdMetricsSelectionChanged() throws PresentationLogicException
	{
		selectInstance();
		updateControlsState();
		
	}

	@Override
	protected void onGrdMetricsSelectionCleared() throws PresentationLogicException
	{
		selectInstance();
		updateControlsState();
		
	}

	@Override
	protected void onGraphingMetricPointClicked(GraphingPoint point)
	{
		if (FormMode.VIEW.equals(form.getMode()) && point.getTag() instanceof VSMetrics)
		{
			form.grdMetrics().setValue((VSMetrics) point.getTag());
			selectInstance();
			updateControlsState();
		}
		
	}
	public void clearInstanceControls()
	{
		clearScreen();
	}

	public void newInstance() throws PresentationLogicException
	{
		form.getLocalContext().setSelectedInstance(null);
		clearInstanceControls();
		form.ccRecording().initializeComponent(true, null); //WDEV-18846
		LastHeightMetricRecordVo lastHeight = domain.getLastRecordedHeight(form.getGlobalContext().Core.getPatientShort());
		if (lastHeight != null)
		{
			form.decHeight().setValue(lastHeight.getValue());
			form.GroupH().setValue(lastHeight.getMeasuredIsNotNull()?(lastHeight.getMeasured().booleanValue()?GroupHEnumeration.rdoHM:GroupHEnumeration.rdoHE):GroupHEnumeration.None);
		}
		form.setMode(FormMode.EDIT);
	}

	public boolean save() throws PresentationLogicException
	{
		VSMetrics record = populateDataFromScreen(form.getLocalContext().getSelectedInstanceIsNotNull()?(VSMetrics) form.getLocalContext().getSelectedInstance().clone():null);
		String[] errors = record.validate(validateUIRules());
		if (errors != null && errors.length>0)
		{
			engine.showErrors(errors);
			return false;
		}
		try
		{
			form.getLocalContext().setSelectedInstance(domain.save(record));
		}
		catch (StaleObjectException e)
		{
			engine.showErrors(new String[]{ConfigFlag.UI.STALE_OBJECT_MESSAGE.getValue()});
			open();
			return false;
		}
		return true;
	}

	public void updateControlsState()
	{
		if (form.getMode().equals(FormMode.VIEW))
		{
			form.btnEdit().setVisible(true);
			form.btnEdit().setEnabled(form.grdMetrics().getValue()!=null);
		}
		else
		{
			form.ccRecording().setEnabledDateTime(false);
		}

	}

	public void updateInstance()
	{
		form.setMode(FormMode.EDIT);

	}

	public void initialize() throws FormOpenException
	{

		form.ccRecording().setLabelsToRecordingBy();
		form.ccRecording().setIsRequiredPropertyToControls(true);
		form.dtimTo().setValue(new DateTime());
		form.dtimFrom().setValue(new DateTime().addMonth(-3));
		form.chkH().setValue(true);
		form.chkW().setValue(true);
		form.graphingMetric().showYAxisValues();
		form.graphingMetric().graphingOptions().metrics.setDisplayBMI(false);
		showHideGraphics();
		form.imgHE().setValue(form.getImages().Nursing.HeightEstimated16);
		form.imgWE().setValue(form.getImages().Nursing.WeightEstimated16);
		form.imgHM().setValue(form.getImages().Nursing.HeightMeasured16);
		form.imgWM().setValue(form.getImages().Nursing.WeightMeasured16);
		
		
		// form.graphingMetric().

	}
	private void showHideGraphics()
	{
		form.graphingMetric().graphingOptions().metrics.setDisplayHeight(form.chkH().getValue());
		form.graphingMetric().graphingOptions().metrics.setDisplayWeight(form.chkW().getValue());
	}
	
	public void open() throws PresentationLogicException
	{
		open(true);
	}
	public void open(boolean fromInit)
	{
		search(!fromInit);
		form.setMode(FormMode.VIEW);
	}

	private void populateListFromData(VSMetricsCollection data)
	{
		clear();
		if (data == null || data.size() == 0)
			return;
		for (int i = 0 ; i < data.size() ; i++)
		{
			addRowToGrid(data.get(i));
			addPointToGraphic(data.get(i));			
		}
		
		
		
	}
	
	private void addPointToGraphic(VSMetrics vsMetrics)
	{
		
		//WDEV-11654 
		form.graphingMetric().addPoint(new GraphingMetrics(vsMetrics.getAuthoringInformation().getAuthoringDateTime(),vsMetrics.getWeightValue(),vsMetrics.getHeightValue(),vsMetrics.getBMI(),vsMetrics));
		
	}

	private void addRowToGrid(VSMetrics vsMetrics)
	{
		if (vsMetrics == null )
			return;
		grdMetricsRow newRow = form.grdMetrics().getRows().newRow();
		newRow.setValue(vsMetrics);
		newRow.setColumnBMI(vsMetrics.getBMI());
		newRow.setColumnDateTime(vsMetrics.getAuthoringInformationIsNotNull()?vsMetrics.getAuthoringInformation().getAuthoringDateTime():null);
		newRow.setColumnHcp(vsMetrics.getAuthoringInformationIsNotNull()?vsMetrics.getAuthoringInformation().getAuthoringHcp():null);
		newRow.setColumnHeight(vsMetrics.getHeightValue());
		newRow.setColumnHEM(vsMetrics.getHeightEstimatedMeasuredIsNotNull() && vsMetrics.getHeightEstimatedMeasured()?form.getImages().Nursing.HeightMeasured16:form.getImages().Nursing.HeightEstimated16);
		newRow.setTooltipForColumnHEM(vsMetrics.getHeightEstimatedMeasuredIsNotNull()&& vsMetrics.getHeightEstimatedMeasured()?"Height was measured":"Height was estimated");
		newRow.setColumnSurface(bodySurfaceArea(vsMetrics.getHeightValue(),vsMetrics.getWeightValue()));
		newRow.setColumnWeight(vsMetrics.getWeightValue());
		newRow.setColumnWEM(vsMetrics.getWeightEstimatedMeasuredIsNotNull() && vsMetrics.getWeightEstimatedMeasured()?form.getImages().Nursing.WeightMeasured16:form.getImages().Nursing.WeightEstimated16);
		newRow.setTooltipForColumnWEM(vsMetrics.getWeightEstimatedMeasuredIsNotNull()&& vsMetrics.getWeightEstimatedMeasured()?"Weight was measured":"Weight was estimated");
		
		populateBMIandSurface();

		
	}

	private void search(boolean showErrors)
	{
		String[] errors = validateSearchCriteria();
		clear();
		if (errors != null && errors.length >0)
		{
			if (showErrors)
				engine.showErrors(errors);
			return;
		}
		
		//WDEV-11654 If selected record has time greater than dateTo change dateTo
		if(form.getLocalContext().getSelectedInstanceIsNotNull() && form.getLocalContext().getSelectedInstance().getAuthoringInformationIsNotNull()
				&& form.getLocalContext().getSelectedInstance().getAuthoringInformation().getAuthoringDateTimeIsNotNull()
				&& form.getLocalContext().getSelectedInstance().getAuthoringInformation().getAuthoringDateTime().isGreaterThan(form.dtimTo().getValue()))
			form.dtimTo().setValue(form.getLocalContext().getSelectedInstance().getAuthoringInformation().getAuthoringDateTime());
				
		VSMetricsCollection metrics = domain.listPatientMetrics(form.getGlobalContext().Core.getPatientShort(),form.dtimFrom().getValue(),form.dtimTo().getValue());
		populateListFromData(metrics);
		if (showErrors && (metrics == null || metrics.size() == 0))
			engine.showMessage("No records found to match your criteria", "No records", MessageButtons.OK, MessageIcon.INFORMATION);
		form.grdMetrics().setValue(form.getLocalContext().getSelectedInstance());
		
		form.getGlobalContext().Nursing.setMetricSearchCriteria(getSearchCriteria()); //WDEV-19389 
		selectInstance();
	}
	
	private MetricSearchCriteriaVo getSearchCriteria()
	{
		MetricSearchCriteriaVo searchCriteria = new MetricSearchCriteriaVo();
		
		searchCriteria.setFromDateTime(form.dtimFrom().getValue());
		searchCriteria.setToDateTime(form.dtimTo().getValue());
		searchCriteria.setPatient(form.getGlobalContext().Core.getPatientShort());
		
		return searchCriteria;
	}
		
	private void setSearchCriteria(MetricSearchCriteriaVo metricSearchCriteriaVo)
	{
		form.dtimFrom().setValue(metricSearchCriteriaVo.getFromDateTime());
		form.dtimTo().setValue(metricSearchCriteriaVo.getToDateTime());
	}
	
	private void selectInstance()
	{
		form.getLocalContext().setSelectedInstance(form.grdMetrics().getValue());
		populateScreenFromData(form.grdMetrics().getValue());		
	}

	private String[] validateSearchCriteria()
	{
		ArrayList<String> errors = new ArrayList<String>();
		if (form.dtimFrom().getValue() == null)
			errors.add("From Date is mandatory");
		if (form.dtimTo().getValue() == null)
			errors.add("To Date is mandatory");
		if (errors.size() == 0)
		{
			if (form.dtimFrom().getValue().isGreaterThan(form.dtimTo().getValue()))
				{
				errors.add("From Date must be before To Date.");
				}
			else
				return null;
		}
		String[] result = new String[errors.size()];
		errors.toArray(result);
		return result;
	}

	@Override
	protected void clearScreen()
	{
		super.clearScreen();
		form.ccRecording().setValue(null);
		form.GroupH().setValue(GroupHEnumeration.None);
		form.GroupW().setValue(GroupWEnumeration.None);
	}

	@Override
	protected void populateScreenFromData(VSMetrics value)
	{
		clearScreen();
		if(value == null)
			return;
		super.populateScreenFromData(value);
		form.ccRecording().setValue(value.getAuthoringInformation());
		form.GroupH().setValue(value.getHeightEstimatedMeasuredIsNotNull()&&value.getHeightEstimatedMeasured()?GroupHEnumeration.rdoHM:GroupHEnumeration.rdoHE);
		form.GroupW().setValue(value.getWeightEstimatedMeasuredIsNotNull()&&value.getWeightEstimatedMeasured()?GroupWEnumeration.rdoWM:GroupWEnumeration.rdoWE);
		populateBMIandSurface();
	}

	@Override
	protected VSMetrics populateDataFromScreen(VSMetrics value)
	{
		VSMetrics result = super.populateDataFromScreen(value);
		if (!result.getPatientIsNotNull())
		{
			result.setPatient(form.getGlobalContext().Core.getPatientShort());
		}
		result.setAuthoringInformation(form.ccRecording().getValue());
		result.setHeightEstimatedMeasured(form.GroupH().getValue()==GroupHEnumeration.rdoHM?true:false);
		result.setWeightEstimatedMeasured(form.GroupW().getValue()==GroupWEnumeration.rdoWM?true:false);
		return result;
	}

	

	@Override
	public String[] validateUIRules()
	{
		ArrayList<String> errors = new ArrayList<String>();
		if (form.decHeight().getValue()==null)
			errors.add("Height is mandatory.");
	
		
		if (form.decWeight().getValue()==null)
			errors.add("Weight is mandatory.");
	
		
		if (form.GroupH().getValue() == GroupHEnumeration.None)
		{
			errors.add("You must specify if Height was estimated or measured.");
		}
		if (form.GroupW().getValue() == GroupWEnumeration.None)
		{
			errors.add("You must specify if Weight was estimated or measured.");
		}
		
		String ccerr = form.ccRecording().getErrors();
		if (ccerr != null)
		{
			errors.add(ccerr);
		}
		
		if (errors.size()==0)
			return null;
		String[] result = new String[errors.size()];
		errors.toArray(result);
		return result;
	}

	@Override
	public void clear()
	{
		super.clear();
		clearScreen();
		form.grdMetrics().getRows().clear();
		form.graphingMetric().clear();
	}
	public void clearSearch()
	{
		form.dtimFrom().setValue(null);
		form.dtimTo().setValue(null);
		//wdev-12457
		form.chkH().setValue(null);
		form.chkW().setValue(null);
		//--------
	}
	private Float bodySurfaceArea(Float height/*cm*/, Float weight/*kg*/)
	{
		if (height == null || weight  == null)
			return null;
		
		//we have to convert the HEIGHT from cm to m as the formula requires m
		return new Float((float)(0.20247 * Math.pow(height.floatValue() / 100.0, 0.725) * Math.pow(weight.floatValue(), 0.425)));
	}
	private Float bodyMassIndex(Float height/*cm*/, Float weight/*kg*/)
	{
		if (height == null || weight  == null)
			return null;
		if (height == 0)
			return null;
		//we have to convert the HEIGHT from cm to m as the formula requires m
		return new Float((float)(weight.floatValue() / (height.floatValue() / 100.0 * height.floatValue() / 100.0)));
	}

	@Override
	protected void onGrdMetricsGridHeaderClicked(int column) throws PresentationLogicException
	{
		switch (column)
		{
			case 0:
				//Sort datetime
				sortAfterDateTime();
				break;
			case 1: 
				//Sort Hcp
				sortAfterHcp();
			default:
				break;
		}
		
	}

	private void sortAfterHcp()
	{
		form.getLocalContext().setRecordingHcpSortOrder(SortOrder.ASCENDING.equals(form.getLocalContext().getRecordingHcpSortOrder())?SortOrder.DESCENDING:SortOrder.ASCENDING);
		VSMetricsCollection values = form.grdMetrics().getValues();
		values.sort(new RecordingHcpComparator(form.getLocalContext().getRecordingHcpSortOrder()));
		form.grdMetrics().getRows().clear();
		for (int i  = 0 ; i< values.size() ; i++)
		{
			addRowToGrid(values.get(i));
		}
		//WDEV-11654 
		if(form.getLocalContext().getSelectedInstanceIsNotNull())
			form.grdMetrics().setValue(form.getLocalContext().getSelectedInstance());
		
		selectInstance();
	}

	private void sortAfterDateTime()
	{
		form.getLocalContext().setRecordingDateTimeSortOrder(SortOrder.ASCENDING.equals(form.getLocalContext().getRecordingDateTimeSortOrder())?SortOrder.DESCENDING:SortOrder.ASCENDING);
		VSMetricsCollection values = form.grdMetrics().getValues();
		values.sort(new RecordingDateTimeComparator(form.getLocalContext().getRecordingDateTimeSortOrder()));
		form.grdMetrics().getRows().clear();
		for (int i  = 0 ; i< values.size() ; i++)
		{
			addRowToGrid(values.get(i));
		}
		//WDEV-11654 
		if(form.getLocalContext().getSelectedInstanceIsNotNull())
			form.grdMetrics().setValue(form.getLocalContext().getSelectedInstance());
		
		selectInstance();
	}
	
	class RecordingDateTimeComparator implements Comparator<VSMetrics>
	{
		private SortOrder  order; 
		public RecordingDateTimeComparator(SortOrder order)
		{
			this.order = order;
		}
		public int compare(VSMetrics o1, VSMetrics o2)
		{
			int direction = 1;
			if (order == SortOrder.DESCENDING)
				direction = -1;
			return direction*o1.getAuthoringInformation().getAuthoringDateTime().compareTo(o2.getAuthoringInformation().getAuthoringDateTime());
		}
		
	}
	class RecordingHcpComparator implements Comparator<VSMetrics>
	{
		private SortOrder  order; 
		public RecordingHcpComparator(SortOrder order)
		{
			this.order = order;
		}
		public int compare(VSMetrics o1, VSMetrics o2)
		{
			int direction = 1;
			if (order == SortOrder.DESCENDING)
				direction = -1;
			return direction*o1.getAuthoringInformation().getAuthoringHcp().compareTo(o2.getAuthoringInformation().getAuthoringHcp());
		}
		
	}


	@Override
	protected void onChkHValueChanged() throws PresentationLogicException
	{
		showHideGraphics();
		
	}

	@Override
	protected void onChkWValueChanged() throws PresentationLogicException
	{
		showHideGraphics();
		
	}
	
	
	

	
}
