/*******************************************************************************
 * This file is part of GECAMed.
 * 
 * GECAMed is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License (L-GPL) as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * GECAMed 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 Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License (L-GPL)
 * along with GECAMed.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * GECAMed is Copyrighted by the Centre de Recherche Public Henri Tudor (http://www.tudor.lu)
 * (c) CRP Henri Tudor, Luxembourg, 2008
 *******************************************************************************/
package lu.tudor.santec.gecamed.billing.utils;

import lu.tudor.santec.gecamed.billing.ejb.entity.beans.Statement;
import lu.tudor.santec.gecamed.billing.gui.BillingModule;

import org.apache.log4j.Logger;


//***************************************************************************
//* Class Definition and Members                                            *
//***************************************************************************

public class StatementWorkflow 
	{
	private static boolean m_ExtendedMode		= false;
	private static boolean m_CheckPermissions	= false;
	
	private static Logger m_Logger = Logger.getLogger ("gecamed.billing.gui.statement.StatementWorkflow");

	public static final int c_CreateAction			= 0;
	public static final int c_SaveAction			= 1;
	public static final int c_CloseAction			= 2;
	public static final int c_OpenAction			= 3;
	public static final int c_PrintAction			= 4;
	public static final int c_SettleAction			= 5;
	public static final int c_RevokeAction			= 6;
	public static final int c_CancelAction			= 7;
	public static final int c_DeleteAction			= 8;
	
	public static final int	c_NewState				= 0;
	public static final int	c_OpenState				= 1;
	public static final int	c_ClosedState			= 2;
	public static final int	c_PrintedState			= 3;
	public static final int	c_SettledState			= 4;
	public static final int	c_CanceledState			= 5;
	public static final int	c_DeletedState			= 6;
	
	public static final int	c_NotAllowed			= -1;

	public static final int	c_DoNothing				= 0;
	public static final int	c_DoSave				= 1;
	public static final int	c_DoClose				= 2;
	public static final int	c_DoOpen				= 3;
	public static final int	c_DoPrint				= 4;
	public static final int	c_DoSettle				= 5;
	public static final int	c_DoRevoke				= 6;
	public static final int	c_DoCancel				= 7;
	public static final int	c_DoDelete				= 8;
	
	public static final String c_NoneRequired   	= "";
	public static final String c_EditStatements   	= "BillingModule.editStatements";
	public static final String c_CloseStatements 	= "BillingModule.closeStatements";
	public static final String c_OpenStatements     = "BillingModule.openStatements";
	public static final String c_PrintStatements  	= "BillingModule.printStatements";
	public static final String c_SettleStatements  	= "BillingModule.settleStatements";
	public static final String c_CancelStatements  	= "BillingModule.cancelStatements";
	public static final String c_DeleteStatements  	= "BillingModule.deleteStatements";
	
	public static final int	c_Always			= 0;
	public static final int c_AllInvoicesPaid	= 1;
	
	
	
	
	
	public static final String[] m_ActionNames	= { "Create",
		                                          	"Save",
		                                          	"Close",
		                                          	"Open",
		                                          	"Print",
		                                          	"Settle",
		                                          	"Revoke",
		                                          	"Cancel",
		                                          	"Delete" };

	public static final String[] m_StateNames	= { "NEW",
        											"OPN",
        											"CLS",
        											"PRN",
        											"SET",
         											"CAN",
        											"DEL" };
	
	private static final int [][] m_StateTable = 
	{
					// CREATE			SAVE				CLOSE				OPEN			  PRINT				SETTLE							REVOKE           CANCEL		          DELETE
	/* NEW */ 		{ c_NewState,		c_OpenState,		c_ClosedState,	    c_NewState,		  c_NewState, 		c_NewState, 	    c_NewState, 	    c_NewState,       c_DeletedState	 },
	/* OPEN */		{ c_OpenState,		c_OpenState, 		c_ClosedState,		c_OpenState,	  c_OpenState, 		c_OpenState,			  c_OpenState,			  c_CanceledState,  c_DeletedState  },	
	/* CLOSED */	{ c_ClosedState,	c_ClosedState, 		c_ClosedState,		c_OpenState,	  c_PrintedState, 	c_PrintedState,		c_PrintedState,		c_CanceledState,  c_ClosedState   },	
	/* PRINTED*/	{ c_PrintedState,	c_PrintedState,		c_PrintedState,		c_PrintedState,	  c_PrintedState,	c_SettledState,		c_PrintedState,	 c_PrintedState,   c_PrintedState  },
	/* SETTLED */	{ c_SettledState,	c_SettledState,		c_SettledState,		c_SettledState,	  c_SettledState,	c_SettledState,		c_PrintedState,	 c_CanceledState,  c_SettledState  },	
	/* CANCELED */	{ c_CanceledState,	c_CanceledState,	c_CanceledState,	c_CanceledState,  c_CanceledState,	c_CanceledState, c_CanceledState, c_CanceledState,  c_CanceledState },
	/* DELETED */	{ c_DeletedState,	c_DeletedState,		c_DeletedState,		c_DeletedState,	  c_DeletedState,	c_DeletedState,  c_DeletedState,  c_DeletedState,   c_DeletedState  }	
	};
	
	private static final int [][] m_ActionTable = 
	{
					// CREATE			SAVE				CLOSE				OPEN			  PRINT				SETTLE								REVOKE           CANCEL											DELETE
	/* NEW */ 		{ c_DoNothing,		c_DoSave,			c_DoClose,			c_DoNothing,	  c_DoNothing,		c_DoNothing, 					c_DoNothing,				 c_DoNothing,				 c_DoDelete 	   },
	/* OPEN */		{ c_DoNothing,		c_DoSave, 			c_DoClose,			c_DoNothing, 	  c_DoNothing, 		c_DoNothing,	  			c_DoNothing,				 c_DoNothing,				 c_DoDelete  	  },	
	/* CLOSED */	{ c_DoNothing,		c_DoSave, 			c_DoNothing,		c_DoOpen, 		  c_DoPrint, 		c_DoNothing,	  			c_DoNothing,				 c_DoNothing,			  c_DoNothing 	  },	
	/* PRINTED*/	{ c_DoNothing,		c_DoSave,			c_DoNothing,		c_DoNothing,	  c_DoPrint,		c_DoSettle,	 				 c_DoNothing,				 c_DoNothing,			  c_DoNothing 	  },
	/* SETTLED */	{ c_DoNothing,		c_DoNothing,		c_DoNothing,		c_DoNothing,	  c_DoPrint,		c_DoNothing,    		c_DoRevoke,				  c_DoNothing,				 c_DoNothing 	  },	
	/* CANCELED */	{ c_DoNothing,		c_DoNothing,		c_DoNothing,		c_DoNothing,	  c_DoNothing,		c_DoNothing,						c_DoNothing,				 c_DoNothing,				 c_DoNothing 	  },
	/* DELETED */	{ c_DoNothing,		c_DoNothing,		c_DoNothing,		c_DoNothing,	  c_DoNothing,		c_DoNothing,						c_DoNothing,				 c_DoNothing,				 c_DoNothing 	  }	
	};
		
	private static final String [][] m_PermissionTable = 
	{
					// CREATE			SAVE				CLOSE				OPEN			  PRINT				SETTLE									 REVOKE               CANCEL											DELETE
	/* NEW */ 		{ c_NoneRequired,	c_EditStatements,	c_CloseStatements,	c_NoneRequired,	  c_NoneRequired,	c_NoneRequired, 		  c_NoneRequired,		    c_NoneRequired,		c_DeleteStatements },
	/* OPEN */		{ c_NoneRequired,	c_EditStatements, 	c_CloseStatements,	c_NoneRequired,   c_NoneRequired, 	c_NoneRequired,	    c_NoneRequired,		    c_NoneRequired,		c_DeleteStatements },	
	/* CLOSED */	{ c_NoneRequired,	c_EditStatements, 	c_NoneRequired,		c_OpenStatements, c_NoneRequired, 	c_NoneRequired,	    c_NoneRequired,		    c_NoneRequired,		c_NoneRequired     },	
	/* PRINTED*/	{ c_NoneRequired,	c_EditStatements,	c_NoneRequired,		c_NoneRequired,	  c_NoneRequired,	c_SettleStatements, c_NoneRequired,		    c_NoneRequired,		c_NoneRequired 	   },
	/* SETTLED */	{ c_NoneRequired,	c_NoneRequired,		c_NoneRequired,		c_NoneRequired,	  c_NoneRequired,	c_NoneRequired,     c_SettleStatements,		c_NoneRequired,		c_NoneRequired 	   },	
	/* CANCELED */	{ c_NoneRequired,	c_NoneRequired,		c_NoneRequired,		c_NoneRequired,	  c_NoneRequired,	c_NoneRequired,			  c_NoneRequired,		    c_NoneRequired,		c_NoneRequired 	   },
	/* DELETED */	{ c_NoneRequired,	c_NoneRequired,		c_NoneRequired,		c_NoneRequired,	  c_NoneRequired,	c_NoneRequired,			  c_NoneRequired,		    c_NoneRequired,		c_NoneRequired 	   }	
	};

	private static final int [][] m_ExtendedStateTable = 
	{
					// CREATE			SAVE				CLOSE				OPEN			  PRINT				SETTLE							REVOKE           CANCEL		          DELETE
	/* NEW */ 		{ c_NewState,		c_OpenState,		c_ClosedState,	    c_NewState,		  c_NewState, 		c_NewState, 	    c_NewState, 	    c_NewState,       c_DeletedState	 },
	/* OPEN */		{ c_OpenState,		c_OpenState, 		c_ClosedState,		c_OpenState,	  c_OpenState, 		c_OpenState,			  c_OpenState,			  c_CanceledState,  c_DeletedState  },	
	/* CLOSED */	{ c_ClosedState,	c_ClosedState, 		c_ClosedState,		c_OpenState,	  c_PrintedState, 	c_PrintedState,		c_PrintedState,		c_CanceledState,  c_ClosedState   },	
	/* PRINTED*/	{ c_PrintedState,	c_PrintedState,		c_PrintedState,		c_OpenState,	  c_PrintedState,	c_SettledState,		c_PrintedState,	 c_PrintedState,   c_PrintedState  },
	/* SETTLED */	{ c_SettledState,	c_SettledState,		c_SettledState,		c_SettledState,	  c_SettledState,	c_SettledState,		c_PrintedState,	 c_CanceledState,  c_SettledState  },	
	/* CANCELED */	{ c_CanceledState,	c_CanceledState,	c_CanceledState,	c_CanceledState,  c_CanceledState,	c_CanceledState, c_CanceledState, c_CanceledState,  c_CanceledState },
	/* DELETED */	{ c_DeletedState,	c_DeletedState,		c_DeletedState,		c_DeletedState,	  c_DeletedState,	c_DeletedState,  c_DeletedState,  c_DeletedState,   c_DeletedState  }	
	};
	
	private static final int [][] m_ExtendedActionTable = 
	{
					// CREATE			SAVE				CLOSE				OPEN			  PRINT				SETTLE								REVOKE           CANCEL											DELETE
	/* NEW */ 		{ c_DoNothing,		c_DoSave,			c_DoClose,			c_DoNothing,	  c_DoNothing,		c_DoNothing, 					c_DoNothing,				 c_DoNothing,				 c_DoDelete 	   },
	/* OPEN */		{ c_DoNothing,		c_DoSave, 			c_DoClose,			c_DoNothing, 	  c_DoNothing, 		c_DoNothing,	  			c_DoNothing,				 c_DoNothing,				 c_DoDelete  	  },	
	/* CLOSED */	{ c_DoNothing,		c_DoSave, 			c_DoNothing,		c_DoOpen, 		  c_DoPrint, 		c_DoNothing,	  			c_DoNothing,				 c_DoNothing,			  c_DoNothing 	  },	
	/* PRINTED*/	{ c_DoNothing,		c_DoSave,			c_DoNothing,		c_DoOpen,	  	  c_DoPrint,		c_DoSettle,	 				 c_DoNothing,				 c_DoNothing,			  c_DoNothing 	  },
	/* SETTLED */	{ c_DoNothing,		c_DoNothing,		c_DoNothing,		c_DoNothing,	  c_DoPrint,		c_DoNothing,    		c_DoRevoke,				  c_DoNothing,				 c_DoNothing 	  },	
	/* CANCELED */	{ c_DoNothing,		c_DoNothing,		c_DoNothing,		c_DoNothing,	  c_DoNothing,		c_DoNothing,						c_DoNothing,				 c_DoNothing,				 c_DoNothing 	  },
	/* DELETED */	{ c_DoNothing,		c_DoNothing,		c_DoNothing,		c_DoNothing,	  c_DoNothing,		c_DoNothing,						c_DoNothing,				 c_DoNothing,				 c_DoNothing 	  }	
	};
		
	private static final String [][] m_ExtendedPermissionTable = 
	{
					// CREATE			SAVE				CLOSE				OPEN			  PRINT				SETTLE									 REVOKE               CANCEL											DELETE
	/* NEW */ 		{ c_NoneRequired,	c_EditStatements,	c_CloseStatements,	c_NoneRequired,	  c_NoneRequired,	c_NoneRequired, 		  c_NoneRequired,		    c_NoneRequired,		c_DeleteStatements },
	/* OPEN */		{ c_NoneRequired,	c_EditStatements, 	c_CloseStatements,	c_NoneRequired,   c_NoneRequired, 	c_NoneRequired,	    c_NoneRequired,		    c_NoneRequired,		c_DeleteStatements },	
	/* CLOSED */	{ c_NoneRequired,	c_EditStatements, 	c_NoneRequired,		c_OpenStatements, c_NoneRequired, 	c_NoneRequired,	    c_NoneRequired,		    c_NoneRequired,		c_NoneRequired     },	
	/* PRINTED*/	{ c_NoneRequired,	c_EditStatements,	c_NoneRequired,		c_NoneRequired,	  c_NoneRequired,	c_SettleStatements, c_NoneRequired,		    c_NoneRequired,		c_NoneRequired 	   },
	/* SETTLED */	{ c_NoneRequired,	c_NoneRequired,		c_NoneRequired,		c_NoneRequired,	  c_NoneRequired,	c_NoneRequired,     c_SettleStatements,		c_NoneRequired,		c_NoneRequired 	   },	
	/* CANCELED */	{ c_NoneRequired,	c_NoneRequired,		c_NoneRequired,		c_NoneRequired,	  c_NoneRequired,	c_NoneRequired,			  c_NoneRequired,		    c_NoneRequired,		c_NoneRequired 	   },
	/* DELETED */	{ c_NoneRequired,	c_NoneRequired,		c_NoneRequired,		c_NoneRequired,	  c_NoneRequired,	c_NoneRequired,			  c_NoneRequired,		    c_NoneRequired,		c_NoneRequired 	   }	
	};
	

	
//***************************************************************************
//* Constructors                                       						*
//***************************************************************************

public StatementWorkflow ()
	{
//	m_CheckPermissions = true;
//	m_ExtendedMode	   = false;
	}

//***************************************************************************
//* Primitives                                       						*
//***************************************************************************
//---------------------------------------------------------------------------

private static String getRequiredPermission (int p_OldState, int p_Action)
{
if (m_ExtendedMode) return m_ExtendedPermissionTable [p_OldState][p_Action];
			   else return m_PermissionTable [p_OldState][p_Action];
}

//---------------------------------------------------------------------------

private static int getNextState (int p_OldState, int p_Action)
{
if (m_ExtendedMode) return m_ExtendedStateTable [p_OldState][p_Action];
   			   else return m_StateTable [p_OldState][p_Action];
}

//---------------------------------------------------------------------------

private static int getAction (int p_OldState, int p_Action)
{
if (m_ExtendedMode) return m_ExtendedActionTable [p_OldState][p_Action];
   			   else return m_ActionTable [p_OldState][p_Action];
}

//---------------------------------------------------------------------------

private static String formatTransition (int p_OldState, int p_Action, int p_NewState)
	{
	String	l_Transition;
	String	l_Prefix;
	
	if (m_ExtendedMode) l_Prefix = "Extended Transition ";
	   			   else l_Prefix = "Regular Transition ";
	
	l_Transition =  l_Prefix +
					m_StateNames [p_OldState] + 
	            	" =[" + m_ActionNames[p_Action] + "]=> " +
	            	m_StateNames [p_NewState];
	
	return l_Transition;
	}

//---------------------------------------------------------------------------

private static boolean isPermitted (int p_OldState, int p_Action)
	{
	String	l_RequiredPermission = c_NoneRequired;
	
	if (m_CheckPermissions) 
		{
		l_RequiredPermission = getRequiredPermission (p_OldState,p_Action);
		if (!c_NoneRequired.equals(l_RequiredPermission))
			{
			return BillingModule.userHasPermission(l_RequiredPermission);
			}
		return true;
		}
	return true;
	}

//---------------------------------------------------------------------------
//***************************************************************************
//* Body		                                       						*
//***************************************************************************

//---------------------------------------------------------------------------

public static void setExtendedMode (boolean p_Extended)
	{
	m_ExtendedMode = p_Extended;
	}

//---------------------------------------------------------------------------

public static void setCheckPermissions (boolean p_CheckPermissions)
	{
	m_CheckPermissions = p_CheckPermissions;
	}

//---------------------------------------------------------------------------

public static int previewStateChange (Statement p_Statement, int p_Action)
	{
	int		l_OldState;
	int		l_NewState;
	int		l_Action;
	String	l_RequiredPermission = c_NoneRequired;

	if (p_Statement == null) return c_DoNothing;

	l_OldState = (p_Statement.getState() != null)?p_Statement.getState().intValue():c_NewState;

	if ((p_Action >= 0) && (p_Action <= m_ActionTable[0].length))
		{
		l_NewState = getNextState (l_OldState,p_Action);
		l_Action   = getAction    (l_OldState,p_Action);
	
		m_Logger.info(formatTransition (l_OldState,p_Action,l_NewState));

		if (!isPermitted (l_OldState,p_Action))
			{
			l_RequiredPermission = getRequiredPermission (l_OldState,p_Action);
			m_Logger.info("User lacks " + l_RequiredPermission + " permission for transition!");
			l_Action = c_NotAllowed;
			}
		}
	else l_Action = c_NotAllowed;

return l_Action;
}

//---------------------------------------------------------------------------

public static int changeStatementState (Statement p_Statement, int p_Action)
	{
	int		l_OldState;
	int		l_NewState;
	int		l_Action;
	String	l_RequiredPermission = c_NoneRequired;
	
	if (p_Statement == null) return c_DoNothing;
	
	l_OldState = (p_Statement.getState() != null)?p_Statement.getState().intValue():c_NewState;
	
	if ((p_Action >= 0) && (p_Action <= m_ActionTable[0].length))
		{
		l_NewState = getNextState (l_OldState,p_Action);
		l_Action   = getAction    (l_OldState,p_Action);
		
		m_Logger.info(formatTransition (l_OldState,p_Action,l_NewState));

		if (isPermitted (l_OldState,p_Action))
			{
			m_Logger.info("Changing state of statement " + p_Statement.formatStatementNumber());
			p_Statement.setState (Integer.valueOf(l_NewState));
			}
		else
			{
			l_RequiredPermission = m_PermissionTable [l_OldState][p_Action];
			m_Logger.info("User lacks " + l_RequiredPermission + " permission for transition!");
			l_Action = c_NotAllowed;
			}
		}
	else l_Action = c_NotAllowed;
	
	return l_Action;
	}

//---------------------------------------------------------------------------

public static String getStatementStateName (Statement p_Statement)
	{
	String l_StateName;
	
	l_StateName = m_StateNames [c_NewState];
	
	if (p_Statement != null)
		l_StateName = m_StateNames [p_Statement.getState().intValue()];
	
	return l_StateName;
	}

//---------------------------------------------------------------------------

//***************************************************************************
//* End Of Class                                                            *
//***************************************************************************
}
