/*
BITS Web Console v.1.1
 October 27 - Adding Flash 5 / XML Compliance
 July 21 - Removed Multisockets connect while loop.
 March28-2000- CheckConnectionStatus updated - added test condition for applet.Multisock
 March29th - Changed to setTimeout from setInterval (more reliable)
		   - xml applet connection methods added (previous)
		   - global timeout method
		   - added multiple console events
		   - removed xml applet connection methods
		   - Flash 5.0 XMLSocket Object
		   - new connection methods
		   		- XMLSENDSOCKET - sends messages within flash 5.0 applet using XMLSOCKET
				- XMLSEND - sends messages within flash 5.0 applet using XML object + bits_isapi
				- XMLAPPLETSENDSOCKET - sends messages using an flash applet using XMLSOCKET
				- XMLAPPLETSEND - sends messages using an flash applet using XML object + bits_isapi
				- XMLOBJECT - uses the ActiveX object "Microsoft.XMLDOM"

*** Console events currently defined *** 
CONSOLE_MULTISOCKETS_CONNECT
CONSOLE_MULTISOCKETS_DISCONNECT
CONSOLE_CONNECT - Connection method
CONSOLE_DISCONNECT - Connection method
CONSOLE_MULTISOCKETS_FAIL - Possiible params: NO_APPLET, INVALID_APPLET, TIMEOUT, or results of GetLastSocketErr();
CONSOLE_USEREVENT_SENT
CONSOLE_USEREVENT_RECEIVED
CONSOLE_PUSHEVENT_RECEIVED
CONSOLE_TIMEOUT
CONSOLE_USEREVENT_NOTHANDLED
CONSOLE_INIT_SUCCESS
CONSOLE_COMM_STATE

CONSOLE_FAIL/MULTISOCKETS/NO_APPLET
CONSOLE_FAIL/MULTISOCKETS/INVALID_APPLET
CONSOLE_FAIL/MULTISOCKETS/TIMEOUT
CONSOLE_FAIL/MULTISOCKETS/SOCKET/ "GetLastSocketErr()"
CONSOLE_FAIL/COMMUNICATIONS_NOT_OPEN/  "GetCommunicationStatus()"

CONSOLE_FAIL/INIT/FAIL_PARAMS
CONSOLE_FAIL/INIT/FAIL_CONNECTION_TYPE
CONSOLE_FAIL/INIT/FAIL_COMMUNICATION

****************************************
*/
//Defines
var BITS_XML = null;
var Socket = null;
// ConnectionMethods
var MULTISOCKETS = 0;
var BITS_ISAPI = 1;
var XMLSENDSOCKET = 2;
var XMLSEND = 3;
var XMLAPPLETSENDSOCKET = 4;
var XMLAPPLETSEND = 5;
var XMLOBJECT = 6;
var LOCAL = 7;

// CommunicationStatus
var COMMUNICATION_CLOSED = 0;
var COMMUNICATION_OPEN = 1;
var COMMUNICATION_IN_USE = 2;

var NOT_CONNECTED = 0;		// ConnectionStatus
var CONNECTED = 1;
var CONNECTION_PENDING = 2;
var CONNECTION_FAILED = 3;
var CONNECTION_LOST = 4;

var PRIMARY = 0;			// Using Server
var SECONDARY = 1;

var MS_CONNECT_TIME = 100;			// Multisockets Connect values
var MAX_CONNECT_WAIT_TIME = 30000;

var CGI_CALL = "/KaosKasino/Console/BITS_ISAPI.DLL?CAS?";	// Path and params to BITS_ISAPI
var COMM_PATH = "/KaosKasino/Cartridges/CommCenter.htm";		// Path to CommCenter.htm

var E_USER = 0;		// Event Types
var E_PUSH = 1;
var E_CONSOLE = 2;

// event timer values
var EventTimerID = null
var EVENT_TIMER_WAIT = 30000;
var EVENT_TIMER_FREQ = 300;
var EVENT_TIMER_START = null;

// Comm checkin
var CommCenterLoaded = false;

//Global variables:
var ConsoleStorage = new Array();	//- Array to store user defined information.

var UserEvents;		//- The one and only UserEvent object
var PushEvents = new Array();		//- Array to hold PushEvent objects
var PushIndex = 0;
var ConsoleEvents = new Array();	//- Array to hold ConsoleEvent objects
var ConsoleIndex = 0;

var CommunicationMethod;	//- MULTISOCKETS or BITS_ISAPI
var CommunicationStatus;	//- COMMUNICATION_OPEN or COMMUNICATION_CLOSED
var ConnectionStatus;		//- NOT_CONNECTED, CONNECTED, CONNECTION_PENDING, CONNECTION_FAILED, CONNECTION_LOST

var ServerAddress = new Array();		//- Array to hold server IP address+Port. [0] = Primary [1] = Secondary
var UsingServer = PRIMARY;		//- PRIMARY or SECONDARY

var TimeoutID;			//- variable to hold TimeoutID for MessageLoop
var BaseSpeed;			//- Speed in milliseconds for MessageLoop timeout.

var UserEventTimes;		//- Array to track UserEvent times taken.

var CmdPrefix;			// Command Prefix
var CmdSuffix;			// Command Suffix

var DAYS_TO_SAVE_COOKIE = 1;	// Number of days to save cookie
var DAYS_TO_RECOVER = 1;		// Number of days to save CriticalData Cookie.

var PageLocked = false;		// Variable for CommFrame to check on Unload: true means an abnormal unload: save console state

// ******************************************** //

//Objects:

/*=====================================================================================
UserEvent( ServerCommand, RespondsTo , Handlers )
Params: ServerCommand – the message to be sent to the Transaction Server.
	 RespondsTo – Array of possible server responses for this command
	 Handlers – Array of function names for each RespondsTo

Members:	ServerCommand – Command to be sent to Transaction Server
		RespondsTo – Array of server responses
		Handlers – Array of Cartridge function names
		EventType - E_USER. The type of event
		StartTime	- The time that this UserEvent was created.
		Handled	- Is this event complete?

Methods: HandleEvent  - This function attempts to match the response passed in to 
		one of its HandledResponses. If a match is found, the ResponseHandler of the 
		same index is called.

Notes: This object is used to encapsulate a server command, possible server responses 
		to that command, and the names of the functions that handle each possible response.
======================================================================================*/
function UserEvent( ServerCommand, RespondsTo, Handlers )
{
	//Initialize members
	this.ServerCommand = ServerCommand;
	this.RespondsTo = RespondsTo;
	this.Handlers = Handlers;
	
	this.EventType = E_USER;
	this.Handled = false;		

	this.StartTime = new Date();	
	// Assign HandleEvent( Event )  method
	this.HandleEvent = HandleEvent;
	
	// Send this event to the CommunicationCenter
	if (!CommFrame.SendMessage(this))
	{
		return false;
	}
	EventTimer(true);
	return true;
}


/*======================================================================================
PushEvent( RespondsTo , Handlers )
Params: RespondsTo – Array of messages this PushEvent responds to 
		Handlers –  Array of function names for each RespondsTo

Members:RespondsTo – The Stimulus this event responds to
		Handlers – Array of Cartridge function names - Stimulus Response

Methods: HandleEvent  - This function attempts to match the response passed in to one 
		of its HandledResponses. If a match is found, the ResponseHandler of the same index 
		is called.

Notes: This object is used to bind server responses to handler functions. 
======================================================================================*/
function PushEvent( RespondsTo, Handlers )
{
	//Initialize members
	this.RespondsTo = RespondsTo;
	this.Handlers = Handlers;

	this.EventType = E_PUSH;
	this.CallCounter = 0;
	
	// Assign HandleEvent( Event )  method
	this.HandleEvent = HandleEvent;
}

/*======================================================================================
ConsoleEvent( HandledResponses, ResponseHandlers )
Params: HandledResponses – Array of possible server responses 
	 ResponseHandlers –  Array of function names for each HandledResponses

Members:	HandledResponses – Array of server responses
		ResponseHandlers – Array of Cartridge function names

Methods: HandleEvent  - This function attempts to match the response passed in to one 
		of its HandledResponses. If a match is found, the ResponseHandler of the same index 
		is called.

Notes: This object is used to bind Console events to handler functions. 
======================================================================================*/
function ConsoleEvent( RespondsTo, Handlers )
{
	//Initialize members
	this.RespondsTo = RespondsTo;
	this.Handlers = Handlers;

	this.EventType = E_CONSOLE;
	this.CallCounter = 0;
	
	// Assign HandleEvent( Event )  method
	this.HandleEvent = HandleEvent;
}


//Functions:

/*======================================================================================
HandleEvent( Stimulus )
Params: Stimulus – a string to be compared to RespondsTo
Returns: Boolean – true if handled. False if this event does not respond to this type of Stimulus.
Notes:	This function is a method of all Event objects. This function tries to match the 
		Stimulus parameter to one of the Event object’s RespondsTo. If no matches 
		are found, false is returned. If a match is found, the Handler of the same 
		index is called.
======================================================================================*/
function HandleEvent( Stimulus, doc )
{
	var handled = false;
	var purl;
	// Check all RespondsTo against the Stimulus
	for ( HEI = 0; HEI < this.RespondsTo.length; HEI ++)
	{
		if (Stimulus.indexOf(this.RespondsTo[HEI]) != -1)
		{
			if (frames.DebugFrame)
			{
				DebugDetail(this,HEI);
			}
			var h = this.Handlers[HEI]
			var tmp = h.substring(0,(h.indexOf("("))) 
			CartridgeFrame.the_handler = eval("CartridgeFrame." + tmp);
			if (h.indexOf("Stimulus") != -1) CartridgeFrame.the_handler(Stimulus, doc);
			else CartridgeFrame.the_handler(doc);
			handled = true;
			
			if (this.EventType == E_USER)
			{
				EventTimer(false);
				this.Handled = true;
				if (CommunicationMethod == BITS_ISAPI)
				{
					//if (frames.ISAPIFrame.thething) frames.ISAPIFrame.history.go(-1);
				}
				if (handled) return handled;
			}
			if (this.EventType == E_PUSH )
			{
				this.CallCounter = this.CallCounter + 1;
				i = this.RespondsTo.length + 2;
				processState("CONSOLE_PUSHEVENT_RECEIVED");
				if (handled) return handled;
			}
			
			if (this.EventType == E_CONSOLE)
			{
				this.CallCounter = this.CallCounter + 1;
				if (handled) return handled;
			}
		}
	}
	return handled;
}

/*======================================================================================
processState( Stimulus )
Params: Stimulus – a string to check Event objects for 
Returns: Nothing
Notes: This function is the Response Dispatch. It attempts to find an Event object that RespondsTo 
		the Stimulus passed in. If an event responds, the matching Handler is executed.
======================================================================================*/
function processState( Stimulus, doc )
{
	if (Stimulus == "")	
	{
		return;
	}
	
	if (frames.DebugFrame)
	{
		DebugOutput(Stimulus);
	}
	// Test for Console Message
	if (Stimulus.indexOf("CONSOLE_") != -1)	
	{
		// If we have ConsoleEvents registered
		if (ConsoleEvents.length > 0 )
		{
			for (i = 0; i < ConsoleEvents.length; i ++)
			{
				// If the ConsoleEvent handled it
				if (ConsoleEvents[i].HandleEvent(Stimulus))
				{
					return;
				}
			}
		}
		return;	// No console events registered.
	}

	// If we have a UserEvent...
	if (UserEvents != null)	
	{
		// And it hasn't been handled yet...
		if (!UserEvents.Handled )
		{
			// If the User Event handled it
			if (UserEvents.HandleEvent(Stimulus, doc))
			{
				if (top.echo_chat) top.echo_chat("EVENT -> " + Stimulus, "DEV");
				// Recursion!
				SetCommunicationStatus(COMMUNICATION_OPEN);
				processState("CONSOLE_USEREVENT_RECEIVED");
				return;
			}
		}
	}
	// If we have PushEvents registered
	if (PushEvents.length > 0 )
	{
		for (i = 0; i < PushEvents.length; i ++)
		{
			// If the PushEvent handled it
			if (PushEvents[i].HandleEvent(Stimulus))
			{
				if (top.echo_chat) top.echo_chat("EVENT -- " + Stimulus, "DEV");
				return;
			}
		}
	}
	
	processState("CONSOLE_USEREVENT_NOTHANDLED/" + Stimulus)
	if (CartridgeFrame.DefaultMessageHandler)
	{
		CartridgeFrame.DefaultMessageHandler(Stimulus, doc);
	}
	return;
}


/*======================================================================================
InsertCartridge( PrimaryAddress, MsgLoopSpeed, ConnType )
Params: PrimaryAddress – IP and Port of BITS to be used.
		MsgLoopSpeed  - Base speed for timers
		ConnType	  - Connection Type – MULTISOCKETS or BITS_ISAPI
Returns: Boolean
Notes:	This function is called by the Cartridge module when it is ready to begin. It sets 
		some internal variables, and starts up the CommunicationCenter by calling 
		InitializeCommunications.
======================================================================================*/
function InsertCartridge( PrimaryAddress, MsgLoopSpeed, ConnType )
{
	if ( PrimaryAddress == null || MsgLoopSpeed == null ||  ConnType == null)
	{
		processState("CONSOLE_FAIL/INIT/FAIL_PARAMS")
		return false;
	}
	if (ConnType < MULTISOCKETS || ConnType > LOCAL)
	{
		processState("CONSOLE_FAIL/INIT/FAIL_CONNECTION_TYPE")
		return false;
	}

	// Initialize parameters
	SetCommunicationStatus(COMMUNICATION_CLOSED);
	UsingServer = PRIMARY;
	ServerAddress = new Array();
	ServerAddress.length = 2;
	ServerAddress[PRIMARY] = PrimaryAddress;
	BaseSpeed = MsgLoopSpeed;

	CartridgePath = frames.CartridgeFrame.document.location.href;	// Set current Cartridge Path

	if (!InitializeCommunications(ConnType))
	{
		SetConnectionState(CONNECTION_FAILED);
		processState("CONSOLE_FAIL/INIT/FAIL_COMMUNICATION")
		return false;
	}
	CommunicationMethod = ConnType;
	
	PageLocked = true;	// Lock in place. Unlock occurs in RemoveCartridge function
	//alert("Page Locked");
	if (frames.DebugFrame)
	{
		SetupDebug();
	}
	processState("CONSOLE_INIT_SUCCESS");
	return true;
}

/*======================================================================================
RemoveCartridge( EmptyStorage )
Params: EmptyStorage – Boolean: true = delete Console Storage.
Returns: Boolean
Notes: This function is called by the Cartridge module when it is ready to terminate. If 
	the EmptyStorage parameter is false, values in Console Storage will not be removed and 
	are available if another Cartridge is loaded. The CommunicationCenter’s CloseCommunication 
	method is called.
======================================================================================*/
function RemoveCartridge( EmptyStorage )
{
	// If we are to kill ConsoleStorage
	if (!CommFrame.CloseCommunication())
	{
		processState("CONSOLE_FAIL/CLOSE_COMMUNICATION")
		return false;
	}
	if (EmptyStorage)	
	{
		ConsoleStorage = new Array();
		ConsoleStorage.length = 0;
	}

	UsingServer = null;
	ServerAddress[0] = null;
	BaseSpeed = null;
	UserEvents = new Array();
	PushEvents = new Array();
	PushIndex = 0;
	ConsoleEvents = new Array();
	ConsoleIndex = 0;
	 	
	if (TimeoutID != null)
	{
		clearTimeout(TimeoutID);
	}

	PageLocked = false;
	SetCommunicationStatus(COMMUNICATION_CLOSED);
	SetConnectionState(NOT_CONNECTED);
	return true;
}


/*======================================================================================
InitializeCommunications(ConnType)
Params: ConnType – connection type: MULTISOCKETS, BITS_ISAPI
Returns: Boolean
Notes: This function is called internally to start the CommunicationCenter. If ConnType 
		is different from the current value of CommunicationMethod, the CommFrame is loaded 
		with the HTML page that contains the new communication method. If ConnType is equal 
		to the current value of CommunicationMethod, the CommunicationCenter’s OpenCommunication 
		method is called.
======================================================================================*/
function InitializeCommunications(ConnType)
{
	// If the new connection type is different from the current type, load the new page into the CommFrame
	SetConnectionState(CONNECTION_PENDING);
	if (ConnType == MULTISOCKETS)
	{

		if (CommunicationMethod != MULTISOCKETS)
		{
			CommFrame.location.href= COMM_PATH +"?C=M";
			return true;
		}
	}

	if (ConnType == BITS_ISAPI)
	{
		if (CommunicationMethod != BITS_ISAPI)
		{
			CommFrame.location.href= COMM_PATH +"?C=I";
			return true;
		}
	}

	if (ConnType == XMLSENDSOCKET)
	{
		if (CommunicationMethod != XMLSENDSOCKET)
		{
			CommFrame.OpenCommunication(ConnType, BaseSpeed, ServerAddress[PRIMARY])
			return true;
		}
	}
	if (ConnType == XMLOBJECT)
	{
		if (CommunicationMethod != XMLOBJECT)
		{
			CommFrame.location.href= COMM_PATH +"?C=I";
			return true;
		}
	}

	if (ConnType == XMLSEND)
	{
		if (CommunicationMethod != XMLSEND)
		{
			CommFrame.OpenCommunication(ConnType, BaseSpeed, ServerAddress[PRIMARY])
			return true;
		}
	}
	if (ConnType == XMLAPPLETSENDSOCKET)
	{
		if (CommunicationMethod != XMLAPPLETSENDSOCKET)
		{
			CommFrame.location.href= COMM_PATH;
			return true;
		}
	}

	if (ConnType == XMLAPPLETSEND)
	{
		if (CommunicationMethod != XMLAPPLETSEND)
		{
			CommFrame.location.href= COMM_PATH;
			return true;
		}
	}
	if (ConnType == LOCAL)
	{
		if (CommunicationMethod != LOCAL)
		{
			CommFrame.location.href= COMM_PATH;
			return true;
		}
	}

	// If we haven't returned by this point, the requested communication page is already in CommFrame.
	// Therefore, we call OpenCommunication, which is normally be called on the communication page onLoad. 
	return CommFrame.OpenCommunication(ConnType, BaseSpeed)
}


/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 * Function:    CommCenterCheckIn
 * Purpose:     fires when the "commcenter" page loads
 * Inputs:      none
 * Returns:     undefined
 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
function CommCenterCheckIn()
{
	CommCenterLoaded = true;
	if (GetConnectionState() == CONNECTION_PENDING)
	{
		CommFrame.OpenCommunication(CommunicationMethod, BaseSpeed, ServerAddress[PRIMARY])
		return;
	}

}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 * Function:    RegisterSecondaryServer
 * Purpose:     adds a secondary server
 * Inputs:      Address - the address of the secondary server
 * Returns:     true
 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
function RegisterSecondaryServer(Address)
{
	ServerAddress[SECONDARY] =	Address;
	return true;
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 * Function:    SetCurrentServer
 * Purpose:     sets the current server
 * Inputs:      ServerNum - the number of the server to set as active
 * Returns:     boolean - pass or fail
 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
function SetCurrentServer(ServerNum)
{
	if (ServerNum < 0 || ServerNum > ServerAddress.length)
	{
		return false;
	}
	if (ServerAddress[ServerNum] != null)
	{
		SetCommunicationStatus(COMMUNICATION_CLOSED);
		SetConnectionState(CONNECTION_PENDING);
		UsingServer = ServerNum;

		if (!CommFrame.OpenCommunication(ConnType, BaseSpeed))
		{
			return false;
		}
		return true;
	}
}

/*======================================================================================
SetCommandPrefix( Prefix )
Params: Prefix – the value to be stored in CmdPrefix.
Returns: Nothing
Notes:	This function allows the Cartridge to set a prefix that will be added to the beginning 
		of outgoing messages.
======================================================================================*/
function SetCommandPrefix( Prefix )
{
	CmdPrefix = Prefix;
}

/*======================================================================================
SetCommandSuffix( Suffix )
Params: Suffix – the value to be stored in CmdSuffix.
Returns: Nothing.
Notes: This function allows the Cartridge to set a suffix that will be added to the end of 
	outgoing messages.
======================================================================================*/
function SetCommandSuffix( Suffix )
{
	CmdSuffix = Suffix;
}

/*======================================================================================
SetCommunicationStatus( Status )
Params: Status – the value to set CommunicationStatus to
Returns: Boolean
Notes: This function sets the value of the CommunicationStatus variable.
======================================================================================*/
function SetCommunicationStatus(Status)
{
	CommunicationStatus = Status;	
	processState("CONSOLE_COMM_STATE/" + Status)
//TODO:	CommStatusChangeTime = new Date();
	return true;
}

/*======================================================================================
GetCommunicationStatus()
Params: None.
Returns: Current value of CommunicationStatus
Notes: This function simply returns the value of the CommunicationStatus variable.
======================================================================================*/
function GetCommunicationStatus()
{
	return CommunicationStatus;
}

/*======================================================================================
SetCommunicationStatus( Status )
Params: Status – the value to set CommunicationStatus to
Returns: Boolean
Notes: This function sets the value of the CommunicationStatus variable.
======================================================================================*/
function SetConnectionState(Status)
{
	ConnectionStatus = Status;
	processState("CONSOLE_CONN_STATE/" + Status)
	return true;
}

/*======================================================================================
GetCommunicationStatus()
Params: None.
Returns: Current value of CommunicationStatus
Notes: This function simply returns the value of the CommunicationStatus variable.
======================================================================================*/
function GetConnectionState()
{
	return ConnectionStatus;
}

/*======================================================================================
CheckConnectionStatus()
Params: None.
Returns: Current value of ConnectionStatus variable.
Notes: This function is used during MultiSockets communication to check if the MultiSockets 
		Applet is connected to a Transaction Server.
======================================================================================*/
function CheckConnectionStatus()
{
	var CurrentStatus;
	
	if (frames.CommFrame.document.applets)
	{
		if (frames.CommFrame.document.applets.MultiSock)
		{
			if (frames.CommFrame.document.applets.MultiSock.isconnected())
			{
				if (GetConnectionState() == CONNECTION_PENDING)
				{
					SetConnectionState(CONNECTED);		// We're connected.
					SetCommunicationStatus(COMMUNICATION_OPEN);
					processState("CONSOLE_MULTISOCKETS_CONNECT");
					processState("CONSOLE_CONNECT/" + CommunicationMethod);
				}
				else
				{
					SetConnectionState(CONNECTED);		// We're connected.
				}
			}
			else							// We're not connected
			{
				// If we were connected last time we checked, the connection has been lost!		
				if (GetConnectionState() == CONNECTED)	
				{
					// Set connection status to Lost
					SetConnectionState(CONNECTION_LOST);
						// Send Console event.					
					processState("CONSOLE_MULTISOCKETS_DISCONNECT");
					processState("CONSOLE_DISCONNECT/" + CommunicationMethod);
				}
				else if (GetConnectionState() == CONNECTION_PENDING)
				{
					
					frames.CommFrame.ConnectionTimer[1] = new Date();
					// If we're still in this loop after 30 seconds...
					if (frames.CommFrame.ConnectionTimer[1] - frames.CommFrame.ConnectionTimer[0] > MAX_CONNECT_WAIT_TIME )
					{
						SetConnectionState(CONNECTION_FAILED);	// No longer pending
						processState("CONSOLE_MULTISOCKETS_FAIL/TIMEOUT");
						processState("CONSOLE_FAIL/MULTISOCKETS/TIMEOUT");
						return false;
					}
					else
					{
						CommFrame.OpenCommunication(CommunicationMethod, BaseSpeed, ServerAddress[UsingServer]);	// haven't connected yet. Try again.
					}
				}
				else
				{
					//processState("CONSOLE_MULTISOCKETS_DISCONNECT");	// Send Console event.
					SetConnectionState(NOT_CONNECTED);		// Set connection status to not connected.
				}
				
			}
		}
	}
	return GetConnectionState();
}


/*======================================================================================
SendUserEvent( TSCmd, RespondsTo , Handlers)
Params:  TSCmd – the BITS command 
	  RespondsTo – an Array of expected responses to TSCmd.
	  Handlers  - an Array of Cartridge handler function names.
Returns: Boolean
Notes: This function is called by the Cartridge to create a UserEvent object. If successful, 
		the UserEvent automatically sends itself to the CommunicationCenter. Otherwise, 
		return false.
======================================================================================*/
function SendUserEvent( TSCmd, RespondsTo , Handlers)
{
	if ( TSCmd == null || RespondsTo == null || Handlers == null)
	{
		processState("CONSOLE_FAIL/FAIL_PARAMS")
		return false;
	}

	var Command; 
	if (GetCommunicationStatus() == COMMUNICATION_OPEN)
	{
		if (UserEvents != null)
		{
			// If the last UserEvent is not finished yet
			if (UserEvents.Handled == false)
			{
				processState("CONSOLE_FAIL/COMMUNICATIONS_NOT_OPEN/" + GetCommunicationStatus())
				return false;
			}
		}

		if (CmdPrefix != null)
		{
			Command = CmdPrefix + TSCmd;
		}
	
		if (CmdSuffix != null)
		{
			Command = Command + CmdSuffix;
		}
		SetCommunicationStatus(COMMUNICATION_IN_USE);
		if (top.echo_chat) top.echo_chat("EVENT <- " + Command, "DEV");
		UserEvents = new UserEvent(Command, RespondsTo, Handlers);
		return true;
	}
	else
	{
		processState("CONSOLE_FAIL/COMMUNICATIONS_NOT_OPEN/" + GetCommunicationStatus())
	}
	return false;
}


/*======================================================================================
RegisterEvent( EventType, RespondsTo, Handlers )
Params: EventType – E_PUSH, E_CONSOLE 
		RespondsTo – an Array of responses to trap
		Handlers  - an Array of Cartridge handler function names.
Returns: Boolean
Notes:	This function is called by the Cartridge to register PushEvents, SystemEvents, 
		and CommEvents with the ResponseDispatch.
======================================================================================*/
function RegisterEvent( EventType, RespondsTo, Handlers )
{
	if (EventType == E_PUSH)
	{
		PushEvents[PushIndex] = new PushEvent(RespondsTo, Handlers);
		PushIndex = PushIndex + 1;
		return true;
	}
	if (EventType == E_CONSOLE)
	{	
		ConsoleEvents[ConsoleIndex] = new ConsoleEvent(RespondsTo, Handlers);
		ConsoleIndex = ConsoleIndex + 1;
		return true;
	}		
	
	return false;
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 * Function: processLocalMessage
 * Purpose:  desc
 * Inputs:   none
 * Returns:  none
 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
 function processLocalMessage(m)
 {
    var op = "00/FAIL/INVALID_CMD";
	for (i=0;i<localMessages.length;i++)
	{
		if (m.indexOf(localMessages[i].Chunk) != -1)
		{
			op = localMessages[i].Output
			i =  localMessages.length;
		}
	}
	setTimeout('processState("' + op + '")', 200);
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* Function: functionName
* Purpose:  desc
* Inputs:   none
* Returns:  none
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
function localMessageObject(chunk, msg)
{
	this.Chunk		= chunk;
	this.Output		= msg;
}

var localMessages = new Array();
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 * Function: functionName
 * Purpose:  desc
 * Inputs:   none
 * Returns:  none
 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
function registerLocalMessage(c, msg)
{ 	
	localMessages[localMessages.length] = new localMessageObject(c, msg);
}



/*======================================================================================
InitializeConsoleStorage( Size )
Params: Size – the length to make the ConsoleStorage array.
		DaysToKeepCookie - number of days from now to expire ConsoleStorage Cookie
Returns: Boolean.
Notes: This function creates a new ConsoleStorage array.
======================================================================================*/
function InitializeConsoleStorage( Size , DaysToKeepCookie)
{
	ConsoleStorage = new Array();
	ConsoleStorage.length = Size;
	DAYS_TO_SAVE_COOKIE = DaysToKeepCookie;
	return true;
}


/*======================================================================================
GetStorageValue( StorageIndex , FromCookie)
Params: StorageIndex – index of the requested value in ConsoleStorage
		FromCookie - Boolean - get value from Cookie
Returns: value at ConsoleStorage[StorageIndex] or null the index is invalid.
Notes: This function returns the ConsoleStorage value at the requested index.
======================================================================================*/
function GetStorageValue( StorageIndex , FromCookie)
{
	if (!FromCookie)
	{
		if (StorageIndex < 0 || StorageIndex > ConsoleStorage.length)
		{
			return null;
		}
		return ConsoleStorage[StorageIndex];
	}
	var StoredCookie = GetCookie("WebCartridge");
	var CookieArray;
	if (StoredCookie == null)
	{
		return null;
	}
	
	CookieArray = StoredCookie.split("/");
	
	if (StorageIndex < 0 || StorageIndex > CookieArray.length)
	{
		return null;
	}
	return CookieArray[StorageIndex];

}

/*======================================================================================
PutStorageValue( StorageValue, StorageIndex, ToCookie )
Params: StorageValue – the value to be stored in ConsoleStorage.
		StorageIndex – the index to store the value at.
		ToCookie - Boolean - put ConsoleStorage in cookie
Returns: Boolean
Notes: This function attempts to store the StorageValue in ConsoleStorage[StorageIndex].
======================================================================================*/
function PutStorageValue( StorageValue, StorageIndex, ToCookie )
{
	if (StorageIndex < 0 || StorageIndex > ConsoleStorage.length)
	{
		return false;
	}
	
	ConsoleStorage[StorageIndex] = StorageValue;
	
	if (!ToCookie)
	{
		return true;
	}
	
	var CStorage = ConsoleStorage.join("/");
	var expire = new Date();
	var expireIn;
	if (DAYS_TO_SAVE_COOKIE > 0)
	{
		expireIn = expire.getTime() + (DAYS_TO_SAVE_COOKIE * 24 * 60 * 60 * 1000);
		expire.setTime(expireIn);
	}
	else
	{
		expire = null;
	}
	
	SetCookie("WebCartridge", CStorage , expire, "/");
	return true;
}


/*======================================================================================
CheckRecovery()
Params: None.
Returns: Boolean
Notes: This function is called by the cartridge to check for a Recovery Cookie in the
user's browser. If present, return true.
======================================================================================*/
function CheckRecovery()
{
	var RecoverCookie = GetCookie("RECOVER");
	var RecoveredData;
	//alert("RecoverCookie:"+RecoverCookie);

	if (RecoverCookie == null || RecoverCookie == "")
	{
		frames.CartridgeFrame.document.location.href=CartridgePath;
		return false;
	}

	return true;
}


function SaveConsoleState()
{
	var CriticalData = new String();
	
	CriticalData = CommunicationMethod + "^" + ServerAddress[0] + "^" + ServerAddress[1] + "^"+ UsingServer + "^" + CartridgePath + "^" + CmdPrefix + "^" + CmdSuffix + "^" + DAYS_TO_SAVE_COOKIE + "^" + ConsoleStorage.length ;

	var expire = new Date();
	var expireIn;

//	expireIn = expire.getTime() + (DAYS_TO_RECOVER * 24 * 60 * 60 * 1000);
//	expire.setTime(expireIn);

	SetCookie("RECOVER", CriticalData , null, "/");
	//alert(CriticalData);
}

function RecoverConsoleState()
{
	var StoredCookie = GetCookie("RECOVER");
	var Params;

	var ConsoleCookie = GetCookie("WebCartridge");
	var StorageArray;

	if (StoredCookie == null)
	{
		frames.CartridgeFrame.document.location.href=CartridgePath;
		return false;
	}
	
	StoredCookie = new String(StoredCookie);
	Params = StoredCookie.split("^");	

	if (Params[1] == "" || Params[4] == "" )
	{
		frames.CartridgeFrame.document.location.href=CartridgePath;
		return false;
	}

	//CommunicationMethod = Params[0];
	ServerAddress[0] = Params[1];
	ServerAddress[1] = Params[2];
	UsingServer = Params[3];
	CartridgePath = Params[4]; 
	CmdPrefix = Params[5];
	CmdSuffix = Params[6];
	DAYS_TO_SAVE_COOKIE = Params[7];

	InitializeConsoleStorage( Params[8] );

	if (ConsoleCookie == null)
	{
		return null;
	}
	
	ConsoleStorage = ConsoleCookie.split("/");
	//alert(ConsoleStorage);
	
	//alert(Params);
	frames.CartridgeFrame.document.location.href=CartridgePath;
//	frames.CommFrame.document.location.href = COMM_PATH;

	DeleteCookie("RECOVER");
	return true;
}

/*======================================================================================
GetLastUserEventTime()
Params: None.
Returns: Time elapsed between creation of the last UserEvent and the Server Response to it.
	 -1 if no events exist, 0 or the UserEvent has not yet been responded to.
Notes: This function can be called by the Cartridge to find out how long it took the last 
		UserEvent to be responded to.
======================================================================================*/
function GetLastUserEventTime()
{
	if (UserEventTimes != null)
	{
		return UserEventTimes;
	}
	return -1;
}


/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 * Function:    DebugOutput
 * Purpose:     Outputs debug information
 * Inputs:      response - a message
 * Returns:     undefined
 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
function DebugOutput(response)
{

	var resp = new String(response);
	var ResponseBuffer = resp.split(CartridgeFrame.DELIMITER);
	var prev;
		
	prev = DebugFrame.document.forms[0].Output.value;
	DebugFrame.document.forms[0].Output.value = "";

	for (i = 0; i < ResponseBuffer.length; i++)
	{
		DebugFrame.document.forms[0].Output.value = DebugFrame.document.forms[0].Output.value + "P"+i+": "+ResponseBuffer[i]+"\r\n";
	}
	DebugFrame.document.forms[0].Output.value = DebugFrame.document.forms[0].Output.value + "---------------\r\n" + prev;
}


/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 * Function:    DebugDetail
 * Purpose:     Outputs debug information
 * Inputs:      e - an event
 				eindex - the index of the handler to echo
 * Returns:     undefined
 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
function DebugDetail(e,eindex)
{
	var Msg;
	var prev = DebugFrame.document.forms[0].Detail.value;
	
	if (e.EventType == E_USER)
	{
		Msg = "UserEvent: ";
	}
	if (e.EventType == E_PUSH)
	{
		Msg = "PushEvent: ";
	}
	if (e.EventType == E_CONSOLE)
	{
		Msg = "ConsoleEvent: ";
	}

	Msg = Msg +  " CartridgeFrame." + e.Handlers[eindex];

	DebugFrame.document.forms[0].Detail.value = Msg + "\r\n" + "-------------------------" + prev;

}
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 * Function:    SetupDebug
 * Purpose:     Sets up the debug frame (if it exists)
 * Inputs:      none
 * Returns:     undefined
 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
function SetupDebug()
{
	var page = "<HTML><HEAD><TITLE></TITLE></HEAD><BODY BGCOLOR='white'><form><textarea name='Output' rows=8 cols=30></textarea><textarea name='Detail' rows=8 cols=30></textarea><input type='text' name='UE' size=6></form></body></HTML>";
	DebugFrame.document.open();
	DebugFrame.document.write(page);
	DebugFrame.document.close();
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 * Function:    EventTimer
 * Purpose:     Times events to make sure they are not timing out (in milliseconds)
 * Inputs:      init - boolean, whether or not this is an initialization. leave blank to initialize
 				wait - how long to wait
				freq - how often to check
				all of these can be left blank to use default values
 * Returns:     undefined
 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
function EventTimer(init, wait, freq)
{
	clearTimeout(EventTimerID)
	if (init == null)
	{
		var now_time = new Date()
		if ((EVENT_TIMER_START + EVENT_TIMER_WAIT) < now_time.getTime())
		{
			//UserEvents.Handled = true;
			processState("CONSOLE_TIMEOUT")
		}
		else
		{
			EventTimerID = setTimeout("EventTimer()", EVENT_TIMER_FREQ)
		}
	}
	else if (init == true)
	{
		var now_time = new Date()
		EVENT_TIMER_START = now_time.getTime()
		if (wait != null) EVENT_TIMER_WAIT = wait;
		if (freq != null) EVENT_TIMER_FREQ = freq;
		EventTimerID = setTimeout("EventTimer()", EVENT_TIMER_FREQ)
	}
}

//----------
//Code from www.cookiecentral.com
//----------
// "Internal" function to return the decoded value of a cookie
//
function getCookieVal (offset) 
{
	var endstr = document.cookie.indexOf (";", offset);
	if (endstr == -1)
	{
		endstr = document.cookie.length;
	}
	return unescape(document.cookie.substring(offset, endstr));
}
//  Function to return the value of the cookie specified by "name".
//    name - String object containing the cookie name.
//    returns - String object containing the cookie value, or null if
//      the cookie does not exist.
function GetCookie (name) 
{
	var arg = name + "=";
	var alen = arg.length;
	var clen = document.cookie.length;
	var i = 0;
	while (i < clen) 
	{
		var j = i + alen;
		if (document.cookie.substring(i, j) == arg)
		{
			return getCookieVal (j);
		}
		i = document.cookie.indexOf(" ", i) + 1;
		if (i == 0) break;
	}
	return null;
}
//  Function to create or update a cookie.
//    name - String object object containing the cookie name.
//    value - String object containing the cookie value.  May contain
//      any valid string characters.
//    [expires] - Date object containing the expiration data of the cookie.  If
//      omitted or null, expires the cookie at the end of the current session.
//    [path] - String object indicating the path for which the cookie is valid.
//      If omitted or null, uses the path of the calling document.
//    [domain] - String object indicating the domain for which the cookie is
//      valid.  If omitted or null, uses the domain of the calling document.
//    [secure] - Boolean (true/false) value indicating whether cookie transmission
//      requires a secure channel (HTTPS).
//
//  The first two parameters are required.  The others, if supplied, must
//  be passed in the order listed above.  To omit an unused optional field,
//  use null as a place holder.  For example, to call SetCookie using name,
//  value and path, you would code:
//
//      SetCookie ("myCookieName", "myCookieValue", null, "/");
//
//  Note that trailing omitted parameters do not require a placeholder.
//
//  To set a secure cookie for path "/myPath", that expires after the
//  current session, you might code:
//
//      SetCookie (myCookieVar, cookieValueVar, null, "/myPath", null,true);
//
function SetCookie (name, value) 
{
	var argv = SetCookie.arguments;
	var argc = SetCookie.arguments.length;
	var expires = (argc > 2) ? argv[2] : null;
	var path = (argc > 3) ? argv[3] : null;
	var domain = (argc > 4) ? argv[4] : null;
	var secure = (argc > 5) ? argv[5] : false;
	document.cookie = name + "=" + escape (value) +
    ((expires == null) ? "" : ("; expires=" + expires.toGMTString())) +
    ((path == null) ? "" : ("; path=" + path)) +
    ((domain == null) ? "" : ("; domain=" + domain)) +
    ((secure == true) ? "; secure" : "");
}

//  Function to delete a cookie. (Sets expiration date to current date/time)
//    name - String object containing the cookie name
//
function DeleteCookie (name) 
{
	var exp = new Date();
	exp.setTime (exp.getTime() - 1);  // This cookie is history
	var cval = GetCookie (name);
	document.cookie = name + "=" + cval + "; expires=" + exp.toGMTString();
}
var CONSOLE_LOADED = true;
if (!document) trace("CONSOLE LOADED");