/FileExtraction/Java_unseen/IMS-MAXIMS_openMAXIMS/Source Library/openmaxims_workspace/Nursing/src/ims/nursing/forms/stoolscale/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 Rory Fitzpatrick using IMS Development Environment (version 1.22 build 41206.1400)
// Copyright (C) 1995-2004 IMS MAXIMS plc. All rights reserved.

package ims.nursing.forms.stoolscale;

import ims.configuration.gen.ConfigFlag;
import ims.core.vo.AuthoringInformationVo;
import ims.core.vo.CareContextShortVo;
import ims.core.vo.CareContextShortVoCollection;
import ims.core.vo.HcpLiteVo;
import ims.domain.exceptions.ForeignKeyViolationException;
import ims.domain.exceptions.StaleObjectException;
import ims.domain.exceptions.UniqueKeyViolationException;
import ims.framework.Control;
import ims.framework.enumerations.FormMode;
import ims.framework.enumerations.SortOrder;
import ims.framework.exceptions.PresentationLogicException;
import ims.framework.utils.Date;
import ims.framework.utils.DateTime;
import ims.framework.utils.Time;
import ims.nursing.forms.stoolscale.GenForm.grdStoolScaleRow;
import ims.nursing.vo.StoolScaleVo;
import ims.nursing.vo.StoolScaleVoCollection;

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

public class Logic extends BaseLogic
{
	// ----------------------------------------------------------------------------------------------------------------------------------------------------
	// Event handlers region
	// ----------------------------------------------------------------------------------------------------------------------------------------------------

	private static final int DATE_HCP_COLUMN = 0;
	/**
	 * On FormOpen event handler
	 */
	protected void onFormOpen() throws ims.framework.exceptions.PresentationLogicException
	{
		initialize();
		open();
	}

	/**
	 * On FormModeChanged event handler
	 */
	protected void onFormModeChanged()
	{
		updateControlsState();
	}

	/**
	 * On RecordBrowserValueChanged event handler
	 */
	protected void onRecbrAssessmentValueChanged() throws PresentationLogicException
	{
		// Populate grid
		displayStoolScaleAssessments(domain.listStoolScaleAssessments(form.recbrAssessment().getValue()));

		// Update controls state
		updateControlsState();
	}

	/**
	 * On GridStoolScaleSelectionChanged event handler
	 */
	protected void onGrdStoolScaleSelectionChanged() throws PresentationLogicException
	{
		// Set selected Stool Assessment
		form.getLocalContext().setStoolScale(form.grdStoolScale().getValue());

		// Populate instance controls
		populateInstanceControlsFromData(form.getLocalContext().getStoolScale());

		// Update instance controls
		updateControlsState();
	}

	/**
	 * On ButtonNewClick event handler
	 */
	protected void onBNewClick() throws ims.framework.exceptions.PresentationLogicException
	{
		newInstance();
	}

	/**
	 * On ButtonUpdateClick event handler
	 */
	protected void onBtnUpdateClick() throws PresentationLogicException
	{
		updateInstance();
	}

	/**
	 * On ButtonSaveClick event handler
	 */
	protected void onBSaveClick() throws ims.framework.exceptions.PresentationLogicException
	{
		if (save())
			open();
	}

	/**
	 * On ButtonCancelClick event handler
	 */
	protected void onBtnCancelClick() throws PresentationLogicException
	{
		open();
	}

	/**
	 * On ContextMenuClickSubmited event handler
	 */
	protected void onContextMenuItemClick(int menuItemID, Control sender) throws PresentationLogicException
	{
		switch (menuItemID)
		{
			case GenForm.ContextMenus.GenericGrid.Add:
				newInstance();
				break;
			case GenForm.ContextMenus.GenericGrid.Update:
				updateInstance();
				break;
		}
	}

	
	// ----------------------------------------------------------------------------------------------------------------------------------------------------
	// Form presentation & logic functions
	// ----------------------------------------------------------------------------------------------------------------------------------------------------

	/**
	 * Initialize the form
	 */
	public void initialize()
	{
		// Hide all options for the context menu
		form.getContextMenus().hideAllGenericGridMenuItems();
		form.customControlAuthoringInfo().setIsRequiredPropertyToControls(true);
	}
	
	/**
	 * Function used to populate the form with date & refresh the form after save or cancel
	 */
	public void open() throws PresentationLogicException
	{
		// Clear the screen
		clearScreen();

		// Populate the record browser with care context that have a stool scale
		// assessment recorded
		populateCareContextRecords(domain.listStoolScaleCareContexts(form.getGlobalContext().Core.getPatientShort()));

		// Select current care context
		form.recbrAssessment().setValue(form.getGlobalContext().Core.getCurrentCareContext());

		// Create a new row for current care context if it is not present in the
		// record browser
		if (form.recbrAssessment().getValue() == null)
		{
			DateTime startDateTime = form.getGlobalContext().Core.getCurrentCareContext().getStartDateTime();
			form.recbrAssessment().newRow(form.getGlobalContext().Core.getCurrentCareContext(), "<Currently selected Care Context> " + startDateTime.getDate().toString() + " " + startDateTime.getTime().toString());
			form.recbrAssessment().setValue(form.getGlobalContext().Core.getCurrentCareContext());
		}

		// Populate the grid with stool scale assessment for selected Care
		// Context
		StoolScaleVoCollection values = domain.listStoolScaleAssessments(form.recbrAssessment().getValue());//WDEV-14975
		
		if(values != null)//WDEV-14975
		{
			form.getLocalContext().setDateHcpSortOrder(SortOrder.DESCENDING);
			values.sort(new StoolScaleDateHCPComparator(form.getLocalContext().getDateHcpSortOrder()));
		}
		
		displayStoolScaleAssessments(values);//WDEV-14975

		// Reselect latest edited stool assessment (if that is the case) &
		// populate the instance controls
		form.grdStoolScale().setValue(form.getLocalContext().getStoolScale());
		form.getLocalContext().setStoolScale(form.grdStoolScale().getValue());
		populateInstanceControlsFromData(form.getLocalContext().getStoolScale());

		// Set form in VIEW mode
		form.setMode(FormMode.VIEW);
	}

	/**
	 * Function used to clear the screen
	 * (grid & instance controls)
	 */
	private void clearScreen()
	{
		// Clear grid
		form.grdStoolScale().getRows().clear();

		// Clear instance controls
		clearInstanceControls();
	}

	/**
	 * Function used to clear the instance controls
	 * Note: It will clear only the controls - not the local or global context
	 */
	public void clearInstanceControls()
	{
		form.customControlAuthoringInfo().setValue(null);
		form.cmbResult().setValue(null);
		form.cmbType().setValue(null);
		form.txtFrequency().setValue(null);
		form.txtDetails().setValue(null);
	}

	/**
	 * Function used to prepare form for creating a new stool scale assessment
	 * Will clear the instance controls, local context, grid selection, initialize the authoring information
	 * and set the form in EDIT mode.
	 */
	public void newInstance() throws PresentationLogicException
	{
		// Clear selected stool scale from local context
		form.getLocalContext().setStoolScale(null);

		// Clear grid selection
		form.grdStoolScale().setValue(form.getLocalContext().getStoolScale());

		// Clear instance controls
		clearInstanceControls();

		// Initialize authoring HCP and recording date
		HcpLiteVo voHcp = (HcpLiteVo) domain.getHcpLiteUser();
		form.customControlAuthoringInfo().initializeComponent();
		form.setcustomControlAuthoringInfoEnabled(true);
		AuthoringInformationVo voAuthoringInformation = new AuthoringInformationVo();

		if (voHcp != null)
			voAuthoringInformation.setAuthoringHcp(voHcp);
	
		DateTime dt = new DateTime(new Date(),new Time());
		voAuthoringInformation.setAuthoringDateTime(dt);
	
		// Set form in edit mode
		form.setMode(FormMode.EDIT);
	}

	/**
	 * Function used to prepare form for editing a stool scale assessment
	 * Will set the form in EDIT mode.
	 */
	public void updateInstance()
	{
		// Set form in edit mode
		form.setMode(FormMode.EDIT);
	}

	/**
	 * Function used to save a stool scale assessment
	 */
	public boolean save() throws PresentationLogicException
	{
		try
		{
			// Get data from screen
			StoolScaleVo stoolAssessment = populateDataFromInstaceControls(form.getLocalContext().getStoolScale() == null ? null : (StoolScaleVo)form.getLocalContext().getStoolScale().clone());

			// Validate data and custom validate
			String[] errors = stoolAssessment.validate();

			errors = customValidate(stoolAssessment, errors);

			if (errors != null && errors.length > 0)
			{
				engine.showErrors(errors);
				return false;
			}

			// Attempt save
			form.getLocalContext().setStoolScale(domain.saveStoolScaleAssessment(stoolAssessment));

			// Return true if save is successful
			return true;
		}
		catch (StaleObjectException exception)
		{
			engine.showMessage(ConfigFlag.UI.STALE_OBJECT_MESSAGE.getValue());
			open();
			return false;
		}
		catch (ForeignKeyViolationException exception)
		{
			engine.showMessage(exception.getMessage());
			return false;
		}
		catch (UniqueKeyViolationException exception)
		{
			engine.showMessage(exception.getMessage());
			return false;
		}
	}

	/**
	 * Function used to perform extra validation on the VO and UI data
	 * @param stoolAssessment - VO to be validated
	 * @param errors - additional errors; pass null for no aditional errors
	 * @return
	 */
	private String[] customValidate(StoolScaleVo stoolAssessment, String[] errors)
	{
		ArrayList<String> listOfErrors = new ArrayList<String>();

		if (errors != null)
		{
			for (int i = 0; i < errors.length; i++)
			{
				listOfErrors.add(errors[i]);
			}
		}

		// Validate from VO
		if (stoolAssessment != null && (stoolAssessment.getDateTimeInitiated()==null || stoolAssessment.getHcpInitiated() == null))
			listOfErrors.add("Authoring Information is mandatory.");
		
		if (stoolAssessment != null && !stoolAssessment.getResultIsNotNull())
			listOfErrors.add("Result is mandatory.");

		int errorCount = listOfErrors.size();

		if (errorCount == 0)
			return null;

		String[] errorsResult = new String[errorCount];

		for (int i = 0; i < listOfErrors.size(); i++)
		{
			errorsResult[i] = listOfErrors.get(i);
		}

		return errorsResult;
	}

	/**
	 * Function used to control the state of controls
	 */
	public void updateControlsState()
	{
		// Button NEW
		form.btnNew().setVisible(FormMode.VIEW.equals(form.getMode()));
		form.btnNew().setEnabled(form.getGlobalContext().Core.getCurrentCareContextIsNotNull() && form.getGlobalContext().Core.getCurrentCareContext().equals(form.recbrAssessment().getValue()));

		// Button EDIT
		form.btnUpdate().setVisible(FormMode.VIEW.equals(form.getMode()) && form.grdStoolScale().getValue() != null);

		// Authoring controls
		form.setcustomControlAuthoringInfoVisible(FormMode.EDIT.equals(form.getMode()));
		form.setcustomControlAuthoringInfoEnabled(FormMode.EDIT.equals(form.getMode()));
		
		// Context menu options
		updateContextMenuState();
	}

	/**
	 * Function used to control the state of context menus
	 */
	private void updateContextMenuState()
	{
		// Add item
		form.getContextMenus().getGenericGridAddItem().setVisible(FormMode.VIEW.equals(form.getMode()) && form.getGlobalContext().Core.getCurrentCareContextIsNotNull() && form.getGlobalContext().Core.getCurrentCareContext().equals(form.recbrAssessment().getValue()));

		// Update item
		form.getContextMenus().getGenericGridUpdateItem().setVisible(FormMode.VIEW.equals(form.getMode()) && form.getGlobalContext().Core.getCurrentCareContextIsNotNull() && form.getGlobalContext().Core.getCurrentCareContext().equals(form.recbrAssessment().getValue()) && form.grdStoolScale().getValue() != null);
	}


	// ----------------------------------------------------------------------------------------------------------------------------------------------------
	// Data exchange functions
	// ----------------------------------------------------------------------------------------------------------------------------------------------------

	/**
	 * Function used to populate the Care Contexts (with stool scale assessments) to record browser 
	 */
	private void populateCareContextRecords(CareContextShortVoCollection careContextList)
	{
		// Clear CareContext list for record browser
		form.recbrAssessment().clear();

		// Terminate function if careContext collection is null
		if (careContextList == null || careContextList.size() == 0)
			return;

		for (int i = 0; i < careContextList.size(); i++)
		{
			CareContextShortVo careContext = careContextList.get(i);

			// Skip null care contexts records
			if (careContext == null)
				continue;

			if (careContext.equals(form.getGlobalContext().Core.getCurrentCareContext()))
				form.recbrAssessment().newRow(careContext, "<Currently selected Care Context> " + careContext.getStartDateTime().getDate().toString() + " " + careContext.getStartDateTime().getTime().toString());
			else
				form.recbrAssessment().newRow(careContext, careContext.getStartDateTime().getDate().toString() + " " + careContext.getStartDateTime().getTime().toString());
		}
	}
	
	/**
	 * Function used to display the stool scale assessments collection in the grid
	 */
	private void displayStoolScaleAssessments(StoolScaleVoCollection stoolScaleList)
	{
		// Clear grid
		form.grdStoolScale().getRows().clear();

		// Terminate function if collection is null
		if (stoolScaleList == null)
			return;

		for (int i = 0; i < stoolScaleList.size(); i++)
		{
			StoolScaleVo stoolScale = stoolScaleList.get(i);

			if (stoolScale == null)
				continue;

			// Create a new row
			grdStoolScaleRow stoolScaleRow = form.grdStoolScale().getRows().newRow();

			// Set row columns
			StringBuffer sb = new StringBuffer();
			sb.append(stoolScale.getDateTimeInitiatedIsNotNull() ? stoolScale.getDateTimeInitiated().toString() : "" );
			if(stoolScale.getHcpInitiatedIsNotNull() && stoolScale.getHcpInitiated().getMosIsNotNull())
			sb.append(" " + stoolScale.getHcpInitiated().getMos().toString());
			stoolScaleRow.setColDate(sb.toString());
			stoolScaleRow.setColNoResult(stoolScale.getResult());
			stoolScaleRow.setColStoolType(stoolScale.getStoolType());
			stoolScaleRow.setColFrequency(stoolScale.getFrequency());
			stoolScaleRow.setTooltipForColFrequency(stoolScale.getFrequency());
			stoolScaleRow.setColDetails(stoolScale.getDetails());
			stoolScaleRow.setTooltipForColDetails(stoolScale.getDetails());

			// Set row value
			stoolScaleRow.setValue(stoolScale);
		}
	}

	/**
	 * Function used to populate the instance controls with data from a StoolScaleVo
	 */
	private void populateInstanceControlsFromData(StoolScaleVo stoolAssessment)
	{
		// Clear instance controls
		clearInstanceControls();

		// Terminate the function if the stool is null
		if (stoolAssessment == null)
			return;

		// Populate instance controls
		AuthoringInformationVo voAuthoringInfo = new AuthoringInformationVo();
		DateTime dt = new DateTime(stoolAssessment.getDateTimeInitiatedIsNotNull() ? stoolAssessment.getDateTimeInitiated().getDate() : null,
				stoolAssessment.getDateTimeInitiatedIsNotNull() ? stoolAssessment.getDateTimeInitiated().getTime() : null);
		voAuthoringInfo.setAuthoringDateTime(dt);
		voAuthoringInfo.setAuthoringHcp(stoolAssessment.getHcpInitiated());
		form.customControlAuthoringInfo().setValue(voAuthoringInfo);

		form.cmbResult().setValue(stoolAssessment.getResult());
		form.cmbType().setValue(stoolAssessment.getStoolType());

		form.txtFrequency().setValue(stoolAssessment.getFrequency());
		form.txtDetails().setValue(stoolAssessment.getDetails());
	}

	/**
	 * Function used to get data from screen into a new StoolScaleVo
	 */
	@SuppressWarnings("unused")
	private StoolScaleVo populateDataFromInstaceControls()
	{
		// Call the function with argument - pass null
		return populateDataFromInstaceControls(null);
	}

	/**
	 * Function used to get data from screen into a new StoolScaleVo
	 */
	private StoolScaleVo populateDataFromInstaceControls(StoolScaleVo stoolScale)
	{
		// Check parameter
		if (stoolScale == null)
			stoolScale = new StoolScaleVo();

		// Set care context
		if(stoolScale.getCareContext()==null)//WDEV-13063 only on New
			stoolScale.setCareContext(form.getGlobalContext().Core.getCurrentCareContext());

		// Get authoring information
		
		AuthoringInformationVo voAuthoringInfo = form.customControlAuthoringInfo().getValue();
		if(voAuthoringInfo!=null){
			stoolScale.setDateTimeInitiated(voAuthoringInfo.getAuthoringDateTime());
			stoolScale.setHcpInitiated(voAuthoringInfo.getAuthoringHcp());
		}

		// Get result
		stoolScale.setResult(form.cmbResult().getValue());
		// Get stool type
		stoolScale.setStoolType(form.cmbType().getValue());
		// Get frequency
		stoolScale.setFrequency(form.txtFrequency().getValue());
		// Get details
		stoolScale.setDetails(form.txtDetails().getValue());

		return stoolScale;
	}

	@Override
	protected void onCustomControlAuthoringInfoValueChanged() throws PresentationLogicException {
		form.customControlAuthoringInfo().setEnabledDateTime(FormMode.EDIT.equals(form.getMode()));
		form.customControlAuthoringInfo().setEnabledAuthoringHCP(FormMode.EDIT.equals(form.getMode()));
	}

	//	WDEV-14975
	@Override
	protected void onGrdStoolScaleGridHeaderClicked(int column)	throws PresentationLogicException 
	{
		StoolScaleVoCollection values = form.grdStoolScale().getValues();
		
		switch(column)
		{
			case DATE_HCP_COLUMN:
				form.getLocalContext().setDateHcpSortOrder(SortOrder.ASCENDING.equals(form.getLocalContext().getDateHcpSortOrder())? SortOrder.DESCENDING : SortOrder.ASCENDING);
				values.sort(new StoolScaleDateHCPComparator(form.getLocalContext().getDateHcpSortOrder()));
			break;	
		}
		
		displayStoolScaleAssessments(values);
	}
	
	//WDEV-14975
	class StoolScaleDateHCPComparator implements Comparator<StoolScaleVo>
	{
		private int order =1;
		
		public StoolScaleDateHCPComparator()
		{
			order = 1;
		}
		
		public StoolScaleDateHCPComparator(SortOrder order)
		{
			this.order = SortOrder.DESCENDING.equals(order)?-1:1;
		}
		
		public int compare(StoolScaleVo o1, StoolScaleVo o2)
		{
			if (o1 != null && o1.getDateTimeInitiatedIsNotNull() && o2!=null && o2.getDateTimeInitiatedIsNotNull())
			{
				Time time1 = o1.getDateTimeInitiated().getTime();
				Time time2 = o2.getDateTimeInitiated().getTime();
				
				time1.setSecond(0);
				time2.setSecond(0);
				
				DateTime dateToCompare1 = new DateTime(o1.getDateTimeInitiated().getDate(), time1);
				DateTime dateToCompare2 = new DateTime(o2.getDateTimeInitiated().getDate(), time2);
				
				int dateOrder = order*dateToCompare1.compareTo(dateToCompare2);
				
				if(dateOrder == 0)
				{
					return compareByHcp(o1, o2);
				}
				
				return dateOrder;
			}
			
			if (o1 == null || !o1.getDateTimeInitiatedIsNotNull())
				return -1*order;
			
			if (o2 == null || !o2.getDateTimeInitiatedIsNotNull())
				return order;
			
			return 0;
		}
		
		private int compareByHcp(StoolScaleVo o1, StoolScaleVo o2)
		{
			if(o1 != null && o1.getHcpInitiatedIsNotNull() && o2 != null && o2.getHcpInitiatedIsNotNull())
			{
				return o1.getHcpInitiated().compareTo(o2.getHcpInitiated());
			}
			
			return 0;
		}	
	}
}
