/*  intfccom.c   */
/*  Copyright 1989 Mountain Math Software  */
/*  All Rights Reserved                    */
#include <string.h>
#include "slist.h"
#include "intfccom.h"
#include "newaloc.h"
#include "remcom.h"
#include "shared.h"
#include "cgidbg.h"

void InterfaceController::SendPacket(DoActionNoCallBack Action,
	const char * String)
{

	int Length = strlen(String) + sizeof(int) + sizeof(Action) ;
	PacketHeader Head(PacketInterfaceControl,CallBackCaseNoCallBack,Length);

	char Buf[MaxPacketSize];
	if (Length > MaxPacketSize) DbgError("InterfaceController::SendPacket",
		"too big");

	int Id = 0 ;
	char * Ptr = Buf ;
	MoveNBytes(Ptr, (char *) &Id, sizeof(Id));
	MoveNBytes(Ptr+=sizeof(Id), (char *) &Action, sizeof(Action));
	MoveNBytes(Ptr+=sizeof(Action), String, strlen(String)) ;
	WriteSeg->WritePacket(Head,Buf);
}

void InterfaceController::SendPacket(ReturnCallBack DoCall,
	DoCallBackAction Action)
{
	// LogOut << "InterfaceController::SendPacket(DoCall)\n" ;

	int Id = IncrementCallBackId();
	// LogOut << "Id = " << Id << "\n" ;
	TheCallBacks->Append( new CallBackEntry(Id,DoCall) );

	int Length = sizeof(Id) + sizeof(Action) ;
	PacketHeader Head(PacketInterfaceControl,CallBackCaseAction,Length);

	char Buf[MaxPacketSize];
	if (Length > MaxPacketSize) DbgError("InterfaceController::SendPacket",
		"too big");

	char * Ptr = Buf ;
	MoveNBytes(Ptr, (char *) &Id, sizeof(Id));
	MoveNBytes(Ptr+=sizeof(Id), (char *) &Action, sizeof(Action));
	WriteSeg->WritePacket(Head,Buf);
}


void InterfaceController::SendPacket(ReturnCallBack DoCall,
	DoCallBackAction Action, int Flag, const char * Name)
{
	// LogOut << "InterfaceController::SendPacket(DoCall,\"" << Name
	//	<< "\")\n" ;

	int Id = IncrementCallBackId();
	// LogOut << "Id = " << Id << "\n" ;
	TheCallBacks->Append( new CallBackEntry(Id,DoCall) );

	int Length = strlen(Name) + sizeof(Id) + sizeof(Action) + sizeof(Flag) ;
	PacketHeader Head(PacketInterfaceControl,CallBackCaseAction,Length);

	char Buf[MaxPacketSize];
	if (Length > MaxPacketSize) DbgError("InterfaceController::SendPacket",
		"too big");

	char * Ptr = Buf ;
	MoveNBytes(Ptr, (char *) &Id, sizeof(Id));
	MoveNBytes(Ptr+=sizeof(Id), (char *) &Action, sizeof(Action));
	MoveNBytes(Ptr+=sizeof(Id), (char *) &Flag, sizeof(Flag));
	MoveNBytes(Ptr+=sizeof(Flag), Name, strlen(Name));

	WriteSeg->WritePacket(Head,Buf);
}

void InterfaceController::DoReturn(int Id, int RemSize,
	const char *  Data)
{
	// LogOut << "InterfaceController::DoReturn\n" ;
	ReturnCallBack DoCall = TheCallBacks->GetCallBack(Id);
	if (!DoCall) DbgError("InterfaceController::DoReturn","bad id");
	if (RemSize != sizeof(int)) DbgError("InterfaceController::DoReturn",
			"bad size");
	int Temp;
	MoveNBytes((char *) &Temp,Data,RemSize);
	// LogOut << "DoCall\n" ;
	DoCall(Temp);
	// LogOut << "Back from DoCall\n" ;
}

void InterfaceController::SendReturnPacketSaveId(int ReturnId,
	ReturnCallBackAction Action, int ReturnValue)
{
	SendReturnPacket(-ReturnId,Action,ReturnValue);
}

void InterfaceController::SendReturnPacket(int ReturnId,
	ReturnCallBackAction Action, int ReturnValue)
{
	// LogOut << "InterfaceController::SendReturnPacket(" << ReturnId <<
	//	", " << Action << ", " << ReturnValue << ")\n" ;
	int ActionSize = sizeof(Action) ;
	int IntSize = sizeof(ReturnValue);
	int Length = IntSize*2 + ActionSize;
	char Buf[MaxPacketSize];
	if (Length > MaxPacketSize) DbgError(
		"InterfaceController::SendReturnPacket", "too big");
	char * Ptr = Buf ;
	MoveNBytes(Ptr,(char *) &ReturnId,IntSize);
	MoveNBytes(Ptr+=IntSize,(char *) &Action,ActionSize);
	MoveNBytes(Ptr+=ActionSize,(char *) &ReturnValue,IntSize);
	PacketHeader Head(PacketInterfaceControl,CallBackCaseReturn,Length);
	WriteSeg->WritePacket(Head,Buf);
}

ReturnCallBack CallBackList::GetCallBack(int id)
{
	int DeleteFlag = 0 ;
	if (id < 0) id = -id ;
	else DeleteFlag = 1 ;
	CallBackListIterator Next(*this) ;
	CallBackEntry * Entry ;
	while (Entry = Next()) if (Entry->GetId() == id) {
		ReturnCallBack Result = Entry->GetCall() ;
		if (DeleteFlag) RemoveEntry(Entry);
		return Result ;
	}
	return 0 ;
}

InterfaceController::InterfaceController()
{
	CallBackId=1;
	TheCallBacks = new CallBackList ;
}


void InterfaceController::Server(PacketHeader& Head, const char * Data)
{
	// LogOut << "InterfaceController::Server\n" ;
	CallBackCase Option = (CallBackCase) Head.Identifier ;
	int Size = Head.DataSize;

	ReturnCallBackAction Action ;
	const ActionSize = sizeof(Action);

	int Id ;
	const IdSize = sizeof(Id);

	int ValueSize = ActionSize + IdSize ;
	int RemSize = Size - ValueSize ;
	const char * AdditionalParameters = 0 ;
	if (RemSize > 0) AdditionalParameters = Data + ValueSize;
	else if (RemSize < 0) DbgError("InterfaceController::Server",
		"bad packet");

	MoveNBytes((char *) &Id,Data,IdSize);
	MoveNBytes((char *) &Action,Data+IdSize,ActionSize) ;
/*
 *	LogOut << "Option = " << Option << ", " << "Action = " <<
 *		Action << ",\nId = " << Id << ", "
 *		<< "RemSize = " << RemSize << "\n" ;
 */

	switch (Option) {
case CallBackCaseAction:
		ActionServer(Id,(DoCallBackAction)Action,RemSize,AdditionalParameters);
		break ;
case CallBackCaseReturn:
		ReturnServer(Id,Action,RemSize,AdditionalParameters);
		break ;
case CallBackCaseNoCallBack:
		ActionNoReturnServer((DoActionNoCallBack)Action,RemSize,
			AdditionalParameters);
		break ;
	}
}

