/*******************************************************************************
 * 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 java.util.Hashtable;

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

import org.apache.log4j.Logger;


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

public class InvoiceWorkflow 
	{
	private static boolean m_ExtendedMode		= false;
	private static boolean m_CheckPermissions	= false;
	private static boolean m_Verbose			= true;
	
	private static Logger m_Logger = Logger.getLogger (InvoiceWorkflow.class.getName());

	public static final int c_CreateAction		= 0;
	public static final int c_SaveAction		= 1;
	public static final int c_VerifyAction		= 2;
	public static final int c_DisproveAction	= 3;
	public static final int c_CloseAction		= 4;
	public static final int c_OpenAction		= 5;
	public static final int c_PrintAction		= 6;
	public static final int c_RemindAction		= 7;
	public static final int c_PayAction			= 8;
	public static final int c_RevokeAction		= 9;
	public static final int c_CancelAction		= 10;
	public static final int c_DeleteAction		= 11;
	
	public static final int	c_OldState			= -1;

	public static final int	c_NewState			= 0;
	public static final int	c_OpenState			= 1;
	public static final int	c_VerifiedState		= 2;
	public static final int	c_ClosedState		= 3; // 2
	public static final int	c_PrintedState		= 4; // 3
	public static final int c_RemindedState		= 5; // 4
	public static final int	c_PaidState			= 6; // 5
	public static final int	c_CanceledState		= 7; // 6
	public static final int	c_DeletedState		= 8; // 7
	
	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_DoUpdate			= 2;
	public static final int	c_DoVerify			= 3;
	public static final int	c_DoDisprove		= 4;
	public static final int	c_DoClose			= 5;
	public static final int	c_DoOpen			= 6;
	public static final int	c_DoPrint			= 7;
//	public static final int c_DoPrintCopy		= 8;	
	public static final int c_DoRemind			= 9;	
	public static final int	c_DoPay				= 10;
	public static final int	c_DoRevoke			= 11;
	public static final int	c_DoCancel			= 12;
	public static final int	c_DoDelete			= 13;
	public static final int c_DoPrintOriginal	= 14;	
	
	public static final String[] m_ActionNames	= { "Create",
		                                          	"Save",
		                                          	"Verify",
		                                          	"Disprove",
		                                          	"Close",
		                                          	"Open",
		                                          	"Print",
		                                          	"Remind",
		                                          	"Pay",
		                                          	"Revoke",
		                                          	"Cancel",
		                                          	"Delete" };

	public static final String[] m_StateNames	= { "NEW",
													"OPN",
													"VER",
				        							"CLS",
        											"PRN",
           											"REM",
           											"PAI",
           										    "CAN",
        											"DEL" };
	private static final String[] XSD_STATE_NAMES = { "new",
													  "open",
													  "verified",
													  "closed",
													  "printed",
													  "reminded",
													  "paid",
													  "canceled",
													  "deleted" };
	
	public static final Hashtable <String,Integer> m_StateLookup = new Hashtable <String,Integer> ();
    
    static 	{
    		m_StateLookup.put( m_StateNames [c_NewState], 		c_NewState);
    		m_StateLookup.put( m_StateNames [c_OpenState], 		c_OpenState);
    		m_StateLookup.put( m_StateNames [c_VerifiedState], 	c_VerifiedState);
    		m_StateLookup.put( m_StateNames [c_ClosedState], 	c_ClosedState);
    		m_StateLookup.put( m_StateNames [c_PrintedState], 	c_PrintedState);
    		m_StateLookup.put( m_StateNames [c_RemindedState], 	c_RemindedState);
    		m_StateLookup.put( m_StateNames [c_PaidState], 		c_PaidState);
    		m_StateLookup.put( m_StateNames [c_CanceledState], 	c_CanceledState);
    		m_StateLookup.put( m_StateNames [c_DeletedState], 	c_DeletedState);
    		//add states as they are defined in the import XSD
    		m_StateLookup.put( XSD_STATE_NAMES [c_NewState], 		c_NewState);
    		m_StateLookup.put( XSD_STATE_NAMES [c_OpenState], 		c_OpenState);
    		m_StateLookup.put( XSD_STATE_NAMES [c_VerifiedState], 	c_VerifiedState);
    		m_StateLookup.put( XSD_STATE_NAMES [c_ClosedState], 	c_ClosedState);
    		m_StateLookup.put( XSD_STATE_NAMES [c_PrintedState], 	c_PrintedState);
    		m_StateLookup.put( XSD_STATE_NAMES [c_RemindedState], 	c_RemindedState);
    		m_StateLookup.put( XSD_STATE_NAMES [c_PaidState], 		c_PaidState);
    		m_StateLookup.put( XSD_STATE_NAMES [c_CanceledState], 	c_CanceledState);
    		m_StateLookup.put( XSD_STATE_NAMES [c_DeletedState], 	c_DeletedState);
    		};
    		
	public static final String c_NoneRequired   	= "";
	public static final String c_EditInvoices   	= "BillingModule.editInvoices";
	public static final String c_VerifyInvoices 	= "BillingModule.verifyInvoices";
	public static final String c_DisproveInvoices 	= "BillingModule.disproveInvoices";
	public static final String c_CloseInvoices 	    = "BillingModule.closeInvoices";
	public static final String c_OpenInvoices  		= "BillingModule.openInvoices";
	public static final String c_PrintInvoices  	= "BillingModule.printInvoices";
	public static final String c_PrintOpenInvoices  = "BillingModule.printOpenInvoices";
	public static final String c_RemindInvoices  	= "BillingModule.remindInvoices";
	public static final String c_SettleInvoices  	= "BillingModule.settleInvoices";
	public static final String c_SettleOpenInvoices = "BillingModule.settleOpenInvoices";
	public static final String c_RevokeInvoices  	= "BillingModule.revokeInvoices";
	public static final String c_CancelInvoices  	= "BillingModule.cancelInvoices";
	public static final String c_DeleteInvoices  	= "BillingModule.deleteInvoices";
		
	//=========================================================================
	//= Regular State and Action Tables
	//=========================================================================
    
    private static final int [][] m_StateTable = 
    {
    //                CREATE             SAVE                VERIFY              DISPROVE             CLOSE               OPEN                PRINT                  REMIND              PAY                     REVOKE              CANCEL            DELETE    
    /* NEW      */  { c_NewState,        c_OpenState,        c_VerifiedState,    c_NewState,          c_ClosedState,      c_NewState,         c_NewState,            c_NewState,         c_NewState,             c_NewState,         c_NewState,       c_DeletedState  },
    /* OPEN     */  { c_OpenState,       c_OpenState,        c_VerifiedState,    c_OpenState,         c_ClosedState,      c_OpenState,        c_PrintedState,        c_OpenState,        c_PaidState,            c_OpenState,        c_OpenState,      c_DeletedState  },    
    /* VERIFIED */  { c_VerifiedState,   c_VerifiedState,    c_VerifiedState,    c_OpenState,         c_ClosedState,      c_VerifiedState,    c_PrintedState,        c_VerifiedState,    c_PaidState,            c_VerifiedState,    c_VerifiedState,  c_DeletedState  },    
    /* CLOSED   */  { c_ClosedState,     c_ClosedState,      c_ClosedState,      c_ClosedState,       c_ClosedState,      c_OldState,         c_PrintedState,        c_ClosedState,      c_PaidState,            c_ClosedState,      c_ClosedState,    c_ClosedState   },
    /* PRINTED  */  { c_PrintedState,    c_PrintedState,     c_PrintedState,     c_PrintedState,      c_PrintedState,     c_PrintedState,     c_PrintedState,        c_RemindedState,    c_PaidState,            c_PrintedState,     c_CanceledState,  c_PrintedState  },
    /* REMINDED */  { c_RemindedState,   c_RemindedState,    c_RemindedState,    c_RemindedState,     c_RemindedState,    c_RemindedState,    c_RemindedState,       c_RemindedState,    c_PaidState,            c_RemindedState,    c_CanceledState,  c_RemindedState },
    /* PAID     */  { c_PaidState,       c_PaidState,        c_PaidState,        c_PaidState,         c_PaidState,        c_PaidState,        c_PaidState,           c_PaidState,        c_PaidState,            c_OldState,         c_CanceledState,  c_PaidState     },    
    /* CANCELED */  { c_CanceledState,   c_CanceledState,    c_CanceledState,    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,         c_DeletedState,     c_DeletedState,   c_DeletedState  }    
    };
    
    private static final int [][] m_ActionTable = 
    {
    //                CREATE             SAVE                VERIFY              DISPROVE             CLOSE               OPEN                PRINT                  REMIND              PAY                     REVOKE              CANCEL            DELETE
    /* NEW      */  { c_DoNothing,       c_DoSave,           c_DoVerify,         c_DoNothing,         c_DoClose,          c_DoNothing,        c_DoNothing,           c_DoNothing,        c_DoNothing,            c_DoNothing,        c_DoNothing,      c_DoDelete  },
    /* OPEN     */  { c_DoNothing,       c_DoUpdate,         c_DoVerify,         c_DoNothing,         c_DoClose,          c_DoNothing,        c_DoPrint,             c_DoNothing,        c_DoPay,                c_DoNothing,        c_DoNothing,      c_DoDelete  },    
    /* VERIFIED */  { c_DoNothing,       c_DoUpdate,         c_DoVerify,         c_DoDisprove,        c_DoClose,          c_DoNothing,        c_DoPrint,             c_DoNothing,        c_DoPay,                c_DoNothing,        c_DoNothing,      c_DoDelete  },    
    /* CLOSED   */  { c_DoNothing,       c_DoNothing,        c_DoNothing,        c_DoNothing,         c_DoClose,          c_DoOpen,           c_DoPrint,             c_DoNothing,        c_DoPay,                c_DoNothing,        c_DoNothing,      c_DoNothing },    
    /* PRINTED  */  { c_DoNothing,       c_DoNothing,        c_DoNothing,        c_DoNothing,         c_DoClose,          c_DoOpen,           c_DoPrint,             c_DoRemind,         c_DoPay,                c_DoNothing,        c_DoNothing,      c_DoNothing },
    /* REMINDED */  { c_DoNothing,       c_DoNothing,        c_DoNothing,        c_DoNothing,         c_DoClose,          c_DoOpen,           c_DoPrint,             c_DoRemind,         c_DoPay,                c_DoNothing,        c_DoNothing,      c_DoNothing },
    /* PAID     */  { c_DoNothing,       c_DoNothing,        c_DoNothing,        c_DoNothing,         c_DoNothing,        c_DoNothing,        c_DoPrint,             c_DoRemind,         c_DoPay,                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,            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,            c_DoNothing,        c_DoNothing,      c_DoNothing }    
    };
        
    private static final String [][] m_PermissionTable =
    {
    //                CREATE             SAVE                VERIFY               DISPROVE            CLOSE               OPEN                PRINT                  REMIND              PAY                     REVOKE              CANCEL               DELETE
    /* NEW      */  { c_NoneRequired,    c_EditInvoices,     c_VerifyInvoices,    c_NoneRequired,     c_CloseInvoices,    c_NoneRequired,     c_NoneRequired,        c_NoneRequired,     c_NoneRequired,         c_NoneRequired,     c_NoneRequired,   c_DeleteInvoices },
    /* OPEN     */  { c_NoneRequired,    c_EditInvoices,     c_VerifyInvoices,    c_NoneRequired,     c_CloseInvoices,    c_NoneRequired,     c_PrintOpenInvoices,   c_NoneRequired,     c_SettleOpenInvoices,   c_NoneRequired,     c_NoneRequired,   c_DeleteInvoices },    
    /* VERIFIED */  { c_NoneRequired,    c_VerifyInvoices,   c_VerifyInvoices,    c_DisproveInvoices, c_CloseInvoices,    c_NoneRequired,     c_PrintInvoices,       c_NoneRequired,     c_SettleInvoices,       c_NoneRequired,     c_NoneRequired,   c_DeleteInvoices },    
    /* CLOSED   */  { c_NoneRequired,    c_NoneRequired,     c_NoneRequired,      c_NoneRequired,     c_CloseInvoices,    c_OpenInvoices,     c_PrintInvoices,       c_NoneRequired,     c_SettleInvoices,       c_NoneRequired,     c_NoneRequired,   c_DeleteInvoices },    
    /* PRINTED  */  { c_NoneRequired,    c_NoneRequired,     c_NoneRequired,      c_NoneRequired,     c_CloseInvoices,    c_OpenInvoices,     c_PrintInvoices,       c_RemindInvoices,   c_SettleInvoices,       c_NoneRequired,     c_NoneRequired,   c_NoneRequired   },
    /* REMINDED */  { c_NoneRequired,    c_NoneRequired,     c_NoneRequired,      c_NoneRequired,     c_CloseInvoices,    c_OpenInvoices,     c_PrintInvoices,       c_RemindInvoices,   c_SettleInvoices,       c_NoneRequired,     c_NoneRequired,   c_NoneRequired   },
    /* PAID     */  { c_NoneRequired,    c_NoneRequired,     c_NoneRequired,      c_NoneRequired,     c_NoneRequired,     c_NoneRequired,     c_PrintInvoices,       c_NoneRequired,     c_SettleInvoices,       c_RevokeInvoices,   c_NoneRequired,   c_NoneRequired   },    
    /* CANCELED */  { c_NoneRequired,    c_NoneRequired,     c_NoneRequired,      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,         c_NoneRequired,     c_NoneRequired,   c_NoneRequired   }    
    };
	
	
	//=========================================================================
	//= Extended State and Action Tables
	//=========================================================================

	private static final int [][] m_ExtendedStateTable = 
	{
					// CREATE			SAVE				VERIFY              DISPROVE			CLOSE				OPEN				      PRINT				        REMIND								     PAY									      REVOKE            CANCEL            DELETE	
	/* NEW */ 		{ c_NewState,		c_OpenState,		c_VerifiedState,	c_NewState,			c_ClosedState,		c_NewState,				  c_NewState,		    c_NewState,						  c_NewState,       c_NewState, 				  c_NewState,       c_DeletedState 	},
	/* OPEN */		{ c_OpenState,		c_OpenState, 		c_VerifiedState,	c_OpenState,		c_ClosedState,		c_OpenState,		   c_PrintedState, 	c_OpenState,						 c_PaidState, 					c_OpenState,			   c_OpenState,      c_DeletedState  },	
	/* VERIFIED */	{ c_VerifiedState,	c_VerifiedState, 	c_VerifiedState,	c_OpenState,		c_ClosedState,		c_VerifiedState,	c_PrintedState, 	c_VerifiedState,			c_PaidState, 					c_VerifiedState,		c_VerifiedState,  c_DeletedState  },	
	/* CLOSED*/		{ c_ClosedState,	c_ClosedState,		c_ClosedState,		c_ClosedState,		c_ClosedState,		c_OldState,			   c_PrintedState,		c_ClosedState,     c_PaidState,						c_ClosedState,		  c_ClosedState,    c_DeletedState  },
	/* PRINTED*/	{ c_PrintedState,	c_PrintedState,		c_PrintedState,		c_PrintedState,		c_PrintedState,		c_PrintedState,		c_PrintedState,		c_RemindedState,   c_PaidState,						c_PrintedState,			c_CanceledState,  c_DeletedState  },
	/* REMINDED*/	{ c_RemindedState,	c_RemindedState,	c_RemindedState,	c_RemindedState,	c_RemindedState,	c_RemindedState,		c_RemindedState,	c_RemindedState,   c_PaidState,						c_RemindedState,		c_CanceledState,  c_DeletedState  },
	/* PAID */		{ c_PaidState,		c_PaidState,		c_PaidState,		c_PaidState,		c_PaidState,		c_PaidState,		   c_PaidState,		   c_PaidState,       c_PaidState,						c_OldState,			    c_CanceledState,  c_DeletedState 	},	
	/* CANCELED */	{ c_CanceledState,	c_CanceledState,	c_CanceledState,	c_CanceledState,	c_CanceledState,	c_CanceledState,	c_CanceledState,	c_CanceledState,   c_CanceledState,		c_CanceledState,		c_CanceledState,  c_DeletedState  },
	/* DELETED */	{ c_DeletedState, 	c_DeletedState,		c_DeletedState,		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				VERIFY				DISPROVE			CLOSE				OPEN							PRINT				     REMIND			   PAY					REVOKE           CANCEL	           DELETE
	/* NEW */ 		{ c_DoNothing,		c_DoSave,			c_DoVerify,			c_DoNothing,		c_DoClose,			c_DoNothing,					c_DoNothing,		     c_DoNothing,      c_DoNothing, 		c_DoNothing,	c_DoNothing,      c_DoDelete 	},
	/* OPEN */		{ c_DoNothing,		c_DoUpdate, 		c_DoVerify,			c_DoNothing,		c_DoClose,			c_DoNothing,					c_DoPrint, 			     c_DoNothing,      c_DoPay,	  			c_DoNothing,	c_DoNothing,      c_DoDelete	},	
	/* VERIFIED */	{ c_DoNothing,		c_DoUpdate, 		c_DoVerify,			c_DoDisprove,		c_DoClose,			c_DoNothing,					c_DoPrint, 			     c_DoNothing,      c_DoPay,	  			c_DoNothing,	c_DoNothing,      c_DoDelete	},	
	/* CLOSED */	{ c_DoNothing,		c_DoUpdate, 		c_DoNothing,		c_DoNothing,		c_DoClose,			c_DoOpen,						c_DoPrint, 			     c_DoNothing,      c_DoPay,	  			c_DoNothing,	c_DoNothing,      c_DoDelete 	},	
	/* PRINTED*/	{ c_DoNothing,		c_DoUpdate,			c_DoNothing,		c_DoNothing,		c_DoClose,			c_DoOpen,						c_DoPrint, 		 c_DoRemind,	   c_DoPay,	 			c_DoNothing,	c_DoNothing,      c_DoDelete 	},
	/* REMINDED*/	{ c_DoNothing,		c_DoUpdate,			c_DoNothing,		c_DoNothing,		c_DoClose,			c_DoOpen,						c_DoPrint,       c_DoRemind,       c_DoPay,	 			c_DoNothing,	c_DoNothing,      c_DoDelete 	},
	/* PAID */		{ c_DoNothing,		c_DoUpdate,			c_DoNothing,		c_DoNothing,		c_DoNothing,		c_DoNothing,					c_DoPrint,	     c_DoRemind,       c_DoPay,    			c_DoRevoke,		c_DoNothing,      c_DoDelete 	},	
	/* CANCELED */	{ c_DoNothing,		c_DoUpdate,			c_DoNothing,		c_DoNothing,		c_DoNothing,		c_DoNothing,					c_DoNothing,		     c_DoNothing,      c_DoNothing,			c_DoNothing,	c_DoNothing,      c_DoDelete    },
	/* DELETED */	{ c_DoNothing,		c_DoUpdate,			c_DoNothing,		c_DoNothing,		c_DoNothing,		c_DoNothing,					c_DoNothing,		     c_DoNothing,      c_DoNothing,			c_DoNothing,	c_DoNothing,      c_DoDelete  	}	
	};

	private static final String [][] m_ExtendedPermissionTable =
	{
					// CREATE			SAVE				VERIFY				DISPROVE			CLOSE				OPEN										PRINT				            REMIND												PAY												       REVOKE            CANCEL	           DELETE
	/* NEW */ 		{ c_NoneRequired,	c_EditInvoices,		c_VerifyInvoices,	c_NoneRequired,		c_CloseInvoices,	c_NoneRequired,		c_NoneRequired,		    c_NoneRequired,   c_NoneRequired, 	 c_NoneRequired,		 c_NoneRequired,   c_DeleteInvoices },
	/* OPEN */		{ c_NoneRequired,	c_EditInvoices, 	c_VerifyInvoices,	c_NoneRequired,		c_CloseInvoices,	c_NoneRequired,		c_PrintOpenInvoices, c_NoneRequired,   c_SettleOpenInvoices, c_NoneRequired,		 c_NoneRequired,   c_DeleteInvoices },	
	/* VERIFIED */	{ c_NoneRequired,	c_VerifyInvoices, 	c_VerifyInvoices,	c_DisproveInvoices,	c_CloseInvoices,	c_NoneRequired,		c_PrintInvoices,     c_NoneRequired,   c_SettleInvoices,     c_NoneRequired,		 c_NoneRequired,   c_DeleteInvoices },	
	/* CLOSED */	{ c_NoneRequired,	c_NoneRequired, 	c_NoneRequired,		c_NoneRequired,		c_CloseInvoices,	c_OpenInvoices,		c_PrintInvoices, 	   c_NoneRequired,   c_SettleInvoices,	    c_NoneRequired,		 c_NoneRequired,   c_DeleteInvoices },	
	/* PRINTED*/	{ c_NoneRequired,	c_NoneRequired,		c_NoneRequired,		c_NoneRequired,		c_CloseInvoices,	c_OpenInvoices,		c_PrintInvoices,	    c_RemindInvoices,	c_SettleInvoices,	    c_NoneRequired,		 c_NoneRequired,   c_DeleteInvoices },
	/* REMINDED*/	{ c_NoneRequired,	c_NoneRequired,		c_NoneRequired,		c_NoneRequired,		c_CloseInvoices,	c_OpenInvoices,		c_PrintInvoices,	    c_RemindInvoices, c_SettleInvoices,	    c_NoneRequired,		 c_NoneRequired,   c_DeleteInvoices },
	/* PAID */		{ c_NoneRequired,	c_NoneRequired,		c_NoneRequired,		c_NoneRequired,		c_NoneRequired,		c_NoneRequired,		c_PrintInvoices,	    c_NoneRequired,   c_SettleInvoices,     c_RevokeInvoices, c_NoneRequired,   c_DeleteInvoices },	
	/* CANCELED */	{ c_NoneRequired,	c_NoneRequired,		c_NoneRequired,		c_NoneRequired,		c_NoneRequired,		c_NoneRequired,		c_NoneRequired,		    c_NoneRequired,   c_NoneRequired,				   c_NoneRequired,		 c_NoneRequired,   c_DeleteInvoices },
	/* DELETED */	{ c_NoneRequired,	c_NoneRequired,		c_NoneRequired,		c_NoneRequired,		c_NoneRequired,		c_NoneRequired,		c_NoneRequired,		    c_NoneRequired,   c_NoneRequired,				   c_NoneRequired,		 c_NoneRequired,   c_DeleteInvoices }	
	};
	
//***************************************************************************
//* Constructors                                       						*
//***************************************************************************
//---------------------------------------------------------------------------

public InvoiceWorkflow ()
	{
//	m_ExtendedMode 	   = false;
//	m_CheckPermissions = 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)
	{
	StringBuffer l_Transition;
	String		l_Prefix;
	
	if (m_ExtendedMode) l_Prefix = "Extended Transition ";
				   else l_Prefix = "Regular Transition ";
	
	l_Transition = new StringBuffer ();
	
	l_Transition.append(l_Prefix)
				.append(m_StateNames [p_OldState])
				.append(" =[")
				.append(m_ActionNames[p_Action])
				.append("]=> ")
				.append(m_StateNames [p_NewState]);
	
	return l_Transition.toString();
	}

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

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 boolean getVerbosity ()
	{
	return m_Verbose;
	}

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

public static void setVerbosity (boolean p_Verbose)
	{
	m_Verbose = p_Verbose;
	}

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

public static boolean getExtendedMode ()
	{
	return m_ExtendedMode;
	}

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

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

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

public static boolean getCheckPermissions ()
	{
	return m_CheckPermissions;
	}

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

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

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

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

	if (p_Invoice == null) return c_DoNothing;

	l_OldState = (p_Invoice.getState() != null)?p_Invoice.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);
		
		if (l_NewState == c_OldState)
			{
			l_NewState = (p_Invoice.getOldState() != null)?p_Invoice.getOldState().intValue():c_OpenState;
			}
		
		if (m_Verbose) 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 changeInvoiceState (Invoice p_Invoice, int p_Action)
	{
	int		l_OldState;
	int		l_NewState;
	int		l_Action;
	String	l_RequiredPermission;
	
	if (p_Invoice == null) return c_DoNothing;
	
	l_OldState = (p_Invoice.getState() != null)?p_Invoice.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);
		
		if (l_NewState == c_OldState) 
			{
			l_NewState = (p_Invoice.getOldState() != null)?p_Invoice.getOldState().intValue():c_OpenState;
			}	
		if (m_Verbose) m_Logger.info("Inv: " + p_Invoice.getId() + " " +formatTransition (l_OldState,p_Action,l_NewState));

		if (isPermitted (l_OldState,p_Action))
			{
			if (m_Verbose) m_Logger.info("Changing state of invoice " + p_Invoice.formatInvoiceNumber(false, true));
			p_Invoice.setState    (Integer.valueOf(l_NewState));
			if (l_NewState != l_OldState) 
				p_Invoice.setOldState (Integer.valueOf(l_OldState));
			else if (p_Action == c_PrintAction 
					&& p_Invoice.getOldState().intValue() < c_PrintedState)
				// the invoice was printed => if in old state, the state would have changed to printed
				p_Invoice.setOldState(Integer.valueOf(c_PrintedState));
			
			}
		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 getInvoiceStateName (Invoice p_Invoice)
	{
	String l_StateName;
	
	l_StateName = m_StateNames [c_NewState];
	
	if (p_Invoice != null)
		l_StateName = m_StateNames [p_Invoice.getState().intValue()];
	
	return l_StateName;
	}

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

public static String getInvoiceStateName (Integer p_InvoiceState)
	{
	String l_StateName;

	l_StateName = m_StateNames [p_InvoiceState.intValue()];

	return l_StateName;
	}

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

public static Integer lookupStateByName (String p_StateName)
	{
	if ((p_StateName != null) && (m_StateLookup.containsKey(p_StateName)))
		 return m_StateLookup.get(p_StateName);
	else return c_NewState;	
	}

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