/*  basic.c   */
/*  Copyright 1989 Mountain Math Software  */
/*  All Rights Reserved                    */
// This file contains the base class on which
// all interactive accessible objects is based
#include "debug.h"
#include "basic.h"
#include "yachead.h"
#include "cgidbg.h"
#include "intfc.h"

#include "outtok.h"


int UserState = 0 ;



UserEntity::UserEntity (const char * Nm):
	Flags(FlagClear),
	Name(Nm),
	TheTargetType(NormalTarget),
	ObjArithType((ArithType::ArithCapabilities)
		ArithType::ArithTypeUndefined)
{
	// LogOut << "UserEntity::ctor for " << Nm << "\n" ;
	ThisType.Type = DecName;
	ThisType.Value.ValName = Name ;
	ThisType.Class = DeclNot ;
	ThisType.Declared = (UserEntity *) 0;
	ThisType.ValueDefined = 0;
	if (!UserState) {
		SetUnusedDefault();
		SetDoNotDelete();
	}
	// LogOut << "Name = " << Nm << ", UserState = " << UserState << ".\n" ;
	if (!GetName() || !*GetName()) DbgError("UserEntity::ctor","null name");
}

UserEntity::~UserEntity()
{
	// LogOut << "UserEntity::dtor for `" << GetName() << "' called.\n" ;
	if (!GetName() || !*GetName()) DbgError("UserEntity::dtor","null name");
}

void UserEntity::SetDoNotDelete()
{
	// LogOut << "SetDoNotDelete for `" << Name << "'.\n" ;
	Flags = (Flag) (Flags | FlagDoNotDelete);
}

int UserEntity::check_safe_delete()
{
	return 1 ;
}

int UserEntity::CheckSafeDelete()
{
	// LogOut << "CheckSafeDelete base function called.\n" ;
	if (!IsDeleteable()) return 0 ;
	return check_safe_delete();
}

void UserEntity::Describe(OutTokens&, ListEntity)
{
	// Out.NextOut(GetName());
	// LogMsg("UserEntity::Describe base function called for ", GetName());
}

void UserEntity::Dump(OutTokens& Out,class ValueTypeList * Lst)
{
	Out.NextOut(GetName());
	ThisType.Dump(Out,Lst);
}

const char * UserEntity::EmitTargetState(OutTokens&)
{
	// LogOut << "UserEnity::EmitTargetState\n" ;
	// Case when there is no state information to emit
	// and thus no function defined in derived class.
	return 0;
}

const char * UserEntity::EmitState(OutTokens&)
{
	// Case when there is no state information to emit
	// and thus no function defined in derived class.
	return 0;
}

int UserEntity::DoEmitState(OutTokens& Out)
{
	// LogOut << "DoEmitState() for `" << GetName() << "'\n" ;
	const char *EmitFirst ;
	// NOTE Code is actually emitted in `EmitState'.
	// This is defined as a virtual function for each separe
	// class of objects.
	while (EmitFirst = EmitState(Out)) {
		UserEntity * Prior = AllEntityLists->GetObject(EmitFirst);
		if (Prior == this) {
			*Output + OutputCppHelp << "Entity `" << EmitFirst
				<< "' made a recursive reference while"
				<< " attempting to save its state.\n" ;
			return 0;
		}
		// LogOut << "Emitting prior entity `" << GetName() << "'\n" ;
		Prior->ClearUnusedDefault();
		Prior->SaveState(Out,CppListState);
	}
	return 1;
}

int UserEntity::DoEmitTargetState(OutTokens& Out)
{
	// LogOut << "DoEmitTargetState() for `" << GetName() << "'XX\n" ;
	const char *EmitFirst ;
	while (EmitFirst = EmitTargetState(Out)) {
		// LogOut << "EmitFirst = 0x" << (void *) EmitFirst << "\n" ;
		UserEntity * Prior = AllEntityLists->GetObject(EmitFirst);
		if (Prior == this) {
			// LogOut << "Recursive reference\n" ;
			*Output + OutputCppHelp << "Entity `" << EmitFirst
				<< "' made a recursive reference while"
				<< " attempting to save its target state.\n" ;
			return 0;
		}
		// LogOut << "Emitting prior entity `" << GetName() << "'\n" ;
		Prior->ClearUnusedDefault();
		Prior->SaveState(Out,CppListTargetState);
	}
	// LogOut << "DoEmitTargetState() for `" << GetName() << "' exit\n" ;
	return 1;
}

int UserEntity::SaveState(OutTokens& Out, CppListCmds Cmd)
{
	// LogOut << "SaveState(" << Cmd << ") for `" << GetName() << "'\n" ;
	int Return ;
	switch (Cmd) {
		case CppListTargetCtor:
		case CppListCtor:
			if (Flags & FlagCppListed) return 1;
			Flags = (Flag) (Flags | FlagCppListed) ;
			// LogOut << "Calling CppList\n" ;
			return CppList(Out,Cmd);
		case CppListState:
			if (Flags & FlagCppStateEmitted) return 1;
			Return = DoEmitState(Out);
			Flags = (Flag) (Flags | FlagCppStateEmitted) ;
			return Return ;
		case CppListTargetState:
			if (Flags & FlagCppTargetStateEmitted) return 1;
			Flags = (Flag) (Flags | FlagCppTargetStateEmitted) ;
			Return = DoEmitTargetState(Out);
/*
 *			LogOut << "SaveState(" << Cmd << ") for `" <<
 *				GetName() << "' exit\n" ;
 */
			return Return ;
		case CppClearDecFlag:
			Flags = (Flag)
				(Flags & ~(FlagCppListed | FlagCppStateEmitted |
				FlagCppTargetStateEmitted)) ;
			return 1;
	}
	return 1 ; // dummy should never execute
}


int UserEntity::CppList(OutTokens&, CppListCmds)
{
/*
 *	LogOut << "UserEntity:CppList - virtual base called for `" <<
 *		GetName() << "'.\n" ;
 */
	return 0;
}


void UserEntity::SetClass(ValueType * Set)
{
	ThisType.Class = Set->Class ;
	ThisType.Type = Set->Type ;
	ThisType.Value = Set->Value ;
	ThisType.Declared = Set->Declared ;
	ThisType.ValueDefined = Set->ValueDefined ;
}

const char * UserEntity::GetName() const
{
	return Name ;
}

int UserEntity::Delete()
{
	if (!CheckSafeDelete()) return 0 ;
	// LogOut << "Deleting: " << GetName() << "\n" ;
	// delete this ;
	return 1 ;
}

UserEntity * MakeDeclaredEntity(UserEntity * Ent, InteractiveEntity *Declar)
{
	ValueType * Temp = new ValueType (DecEnt,Ent,DoDeclEntity,Declar);
	Temp->ValueDefined=1;
	Ent->SetClass(Temp);
	delete Temp ;
	return Ent ;
}

void EntityList::Delete(const char * Name)
{
	EntityListIterator Next(*this);
	UserEntity * Item ;
	while (Item = Next()) if (!strcmp(Item->GetName(),Name)) {
		RemoveEntry((Entity) Item);
		return ;
	}
}

void UserEntity::DoSetTargetType(TargetType type)
{
	TheTargetType = type ;
}

InteractiveEntity * UserEntity::interactive_entity() const
{
	return ThisType.interactive_entity();
}

const char * UserEntity::GetClassName() const
{
	// ValueType * Value = GetValue();
	// if (!Value) {
/*
 *		LogOut << "UserEntity::GetClassName for `" <<
 *			GetName() << "' no value.\n" ;
 */
	//	return 0 ;
	// }
	// return Value->GetClassName();
	return ThisType.GetClassName();
}

