/*
*
* Sample program for use with the Product
* Licensed Materials  - Property of IBM
* 5724-I66
* (c) Copyright IBM Corp.  2009
*   
*/
package com.ibm.wbit.tel.client.jsf.handler;

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

import com.ibm.bpc.clientcore.ClientException;
import com.ibm.bpc.clientcore.MessageWrapper;
import com.ibm.bpe.api.ProcessInstanceData;
import com.ibm.bpe.jsf.handler.ItemListener;
import com.ibm.bpe.jsf.handler.ItemProvider;
import com.ibm.task.clientmodel.HTMConnection;
import com.ibm.wbit.tel.client.jsf.bean.BCInstance;
import com.ibm.wbit.tel.client.jsf.bean.ToDoInstance;
import com.ibm.wbit.tel.client.jsf.infrastructure.FacesUtils;
import com.ibm.wbit.tel.client.jsf.infrastructure.Messages;
import com.ibm.wbit.tel.client.jsf.query.BCGetTaskQuery;


/** 
 * <code>BCDetailsHandler</code> acts as listener for command links in the list
 * of business processes.
 * It extends <code>SubviewHandler</code> to bring up a page which shows input 
 * and output message of the selected business process.   
 * Furthermore it is an ItemProvider and can therefore be used as a model 
 * in the command bar component, which allows lifecycle operations like
 * suspend and resume on the business process. 
 */
public class BCDetailsHandler extends SubviewHandler implements ItemListener, ItemProvider {

    /**
     * The Process Instance bean that should be displayed.
     */
    private BCInstance processInstanceBean;

    /**
     * Connection to Human Task Manager to execute the query
     */
    private HTMConnection connection;

    /**
     * The inline originating human task which initiated the
     * business process.
     */
	private ToDoInstance toDoInstance;
	
	/**
	 * Determine if the task has an output message defined.
	 */
	private boolean outputMessageDefined;
    
    /** 
     * Provide the <code>BCInstance</code> displayed on the page,
     * e.g. to the command bar component.
	 * @see com.ibm.bpe.jsf.handler.ItemProvider#getSelectedItems()
	 */
	public List<BCInstance> getSelectedItems() {
		
		List<BCInstance> list = Collections.emptyList();
		if (processInstanceBean != null) {
			list =	new ArrayList<BCInstance>(1);
			list.add(processInstanceBean);
		}
		return list;
	}
	
	/**
	 * Get the <code>BCInstance</code> selected in list.
	 * 
	 * @return BCInstance
	 */
    public BCInstance getProcessInstanceBean() {
        return processInstanceBean;
    }

	/**
	 * This method is called by the <bpe:list> tag when the user clicks
	 * on one of the displayed business processes.
	 * @param item The selected business process.
	 * @see com.ibm.bpe.jsf.handler.ItemListener#itemChanged(java.lang.Object)
	 */
	public void itemChanged(final Object item) throws ClientException {
		nextSubviewInput((String) null);
		nextSubviewOutput((String) null);
		outputMessageDefined = false;

		// reset the cached ToDoInstance
		toDoInstance = null;

		if (item != null && item instanceof BCInstance) {
			processInstanceBean = (BCInstance) item;

	        //get the component name of the selected business case instance.
	        final BCCheckHandler checkHandler = (BCCheckHandler) FacesUtils.getManagedBeanInstance("bcCheckHandler", BCCheckHandler.class);

			setNavigationInfo(Messages.getString("LINE_BCCHECK_STATE", FacesUtils.getLocale())+" > " + checkHandler.getBcCheckInstance().getComponentName() + " > " + Messages.getString("LINE_BCDETAILS", FacesUtils.getLocale()) + " > " + processInstanceBean.getName());
			
			final ToDoInstance toDoInstance = getInitiatingOTask();
			
			
			// get input message and convert to HashMap
			Object object = toDoInstance.getInputMessageWrapper().getMessage();
			toDoInstance.setInputValuesAll( object );
			
			nextSubviewInput(toDoInstance);

			// outputmessage defined?
			String outputMessageType = toDoInstance.getOutputMessageTypeName();
			if (outputMessageType != null) {
				nextSubviewOutput(toDoInstance);
				outputMessageDefined = true;
				MessageWrapper outputMessage = toDoInstance.getOutputMessageWrapper();
				// does outputmessage already contain values?
				if (outputMessage != null && outputMessage.getMessage() != null) {
					object = outputMessage.getMessage();
					toDoInstance.setOutputValuesAll( object ); 
				}
			} else {
				toDoInstance.setOutputValuesAll((HashMap<String, Object>) null);
			}
		}
	}

	/**
	 * Get the initiating inline human task which started the business process.
	 * The query returns the first inline originating task which in most cases
	 * is the initiating task.
	 * 
	 * @return The task instance with the lowest activation time.
	 * @throws ClientException
	 */
	public ToDoInstance getInitiatingOTask() throws ClientException
	{
		if (toDoInstance == null)
		{
			final BCGetTaskQuery query = new BCGetTaskQuery(processInstanceBean.getID());
			query.setConnection(getConnection());
			toDoInstance = (ToDoInstance) query.execute().get(0);
		}	
		
		return toDoInstance;
	}


	/**
	 * @return the connection
	 */
	public HTMConnection getConnection() {
		return connection;
	}


	/**
	 * @param connection the connection to set
	 */
	public void setConnection(HTMConnection connection) {
		this.connection = connection;
	}
	
	/**
	 * Check if the initiating originating task has an output message.
	 * @return true if the task has an output message.
	 */
	public boolean isOutputMessageDefined()
	{
	 	return outputMessageDefined;
	}
	
	/**
	 * Check if the business process has terminated.
	 */
	public boolean isFinished()
	{
		return getProcessInstanceBean().getExecutionState() == ProcessInstanceData.STATE_FINISHED;
	}
	
	/**
	 * Check if the business process is running.
	 */
	public boolean isRunning()
	{
		return getProcessInstanceBean().getExecutionState() == ProcessInstanceData.STATE_RUNNING;
	}
	
	/**
	 * Check if the business process is suspended.
	 */
	public boolean isSuspended()
	{
		return getProcessInstanceBean().getExecutionState() == ProcessInstanceData.STATE_SUSPENDED;
	}
	
	/**
	 * Check if the business process has terminated.
	 */
	public boolean isTerminated()
	{
		return getProcessInstanceBean().getExecutionState() == ProcessInstanceData.STATE_TERMINATED;
	}
			
	/**
	 * Check if the business process is in a state in which it can be deleted.
	 */
	public boolean isDeletable()
	{
		return isFinished() || isTerminated();
	}
	
	/**
	 * Check if the business process is in a state in which it can be terminated.
	 */
	public boolean isTerminatable()
	{
		return isRunning() || isSuspended();
	}
}
