//
// ObjectWithWidgetsData.cpp
//
//	Copyright © Nemetschek North America, Inc  2005.
//	All Rights Reserved.

#include "StdAfx.h"

#include "ObjectWithWidgetsData.h"

#include "CustomObjects.h"

// 	Index into Parameter list inside the record node is 1-based.
// 	must match Universal 'Prm#' resource or 'PARM' resource 
const short kTextParamIndex				= 1;	
const short kUseCustomTextParamIndex	= 2;
const short kPopupIndex					= 3;
const short kNormalPopupIndex			= 4;


// ---------------------------------------------------------------------------------
CPersistentString::CPersistentString()
	: fStringLen( 0 )
	, fAllocatedSize( 0 )
	, fpString( NULL )
{
}

CPersistentString::CPersistentString(const TXString& src)
	: fStringLen( 0 )
	, fAllocatedSize( 0 )
	, fpString( NULL )
{
	this->operator = ( src );
}

CPersistentString::CPersistentString(const CPersistentString& src)
	: fStringLen( 0 )
	, fAllocatedSize( 0 )
	, fpString( NULL )
{
	this->operator = ( src );
}

CPersistentString::~CPersistentString()
{
	if ( fpString ) {
		::GS_DisposePtr( gCBP, fpString );
	}
	fAllocatedSize	= 0;
	fpString		= NULL;
	fStringLen		= 0;
}

CPersistentString& CPersistentString::operator=(const TXString& src)
{
	if ( this->AllocateLength( src.GetLength() ) ) {
		src.CopyInto( fpString );
		fStringLen	= src.GetLength();
	}
	return *this;
}

CPersistentString&  CPersistentString::operator=(const CPersistentString& src)
{
	if ( this->AllocateLength( src.fStringLen ) ) {
		for(size_t i=0; i<=src.fStringLen; i++) {
			fpString[i]	= src.fpString[i];
		}
		fStringLen	= src.fStringLen;
	}
	return *this;
}

CPersistentString::operator TXString() const
{
	TXString	res;
	if ( fpString && fStringLen > 0 ) {
		res = fpString;
	}
	return res;
}

bool CPersistentString::AllocateLength(size_t len)
{
	fStringLen		= 0;

	if ( fpString && fAllocatedSize < len ) {
		::GS_DisposePtr( gCBP, fpString );
		fAllocatedSize	= 0;
		fpString		= NULL;
	}

	if ( fpString == NULL ) {
		fAllocatedSize	= len + 1;
		fpString		= (char*) ::GS_NewPtr( gCBP, fAllocatedSize );
	}

	return fpString;
}

// ---------------------------------------------------------------------------------
SObjectWithWidgetsData::SObjectWithWidgetsData()
{
	fbPopupListDirty	= false;
}

SObjectWithWidgetsData::~SObjectWithWidgetsData()
{
}

bool SObjectWithWidgetsData::IsPopupListDirty() const
{
	return fbPopupListDirty;
}

void SObjectWithWidgetsData::ClearPopupListDirty()
{
	fbPopupListDirty	= false;
}

const TVWMemoryStringArray& SObjectWithWidgetsData::GetPopupList() const
{
	return farrPopupList;
}

TVWMemoryStringArray& SObjectWithWidgetsData::GetPopupListForEdit()
{
	fbPopupListDirty	= true;
	return farrPopupList;
}

// ---------------------------------------------------------------------------------
CObjectWithWidgetsObjectData::CObjectWithWidgetsObjectData(long userData)
{
	fhObject				= NULL;
	fhFormat				= NULL;
	fhRecord				= NULL;
	fpUserData				= (SObjectWithWidgetsData*) userData;

	this->InitValidFlags();
}

CObjectWithWidgetsObjectData::~CObjectWithWidgetsObjectData()
{
}

void CObjectWithWidgetsObjectData::InitUserdata(bool bSetup)
{
	if ( bSetup ) {
		ASSERTN( kEveryone, fpUserData == NULL );
		fpUserData		= NULL;
		// Construct explicitly with 'placement new'. Get memory from the app because
		// memory allocated with normal 'new' disappears when the dll unloads.
		void* pRawMemory = ::GS_NewPtr( gCBP, sizeof(SObjectWithWidgetsData) );
		if ( pRawMemory ) {
			fpUserData= (SObjectWithWidgetsData*) new(pRawMemory) SObjectWithWidgetsData();	
		}
	}
	else {
		// Destruct explicitly when using 'placement new'
		if ( fpUserData ) {
			fpUserData->~SObjectWithWidgetsData();
			::GS_DisposePtr( gCBP, fpUserData );
			fpUserData = NULL;
		}
	}
}

void CObjectWithWidgetsObjectData::InitValidFlags()
{
	fTextValid				= false;
	fUseCustomTextValid		= false;
	fPopupTextValid			= false;
	fNormalPopupTextValid	= false;
}

bool CObjectWithWidgetsObjectData::SetObject(MCObjectHandle objHand)
{
	fhObject				= objHand;
	fhFormat				= NULL;
	fhRecord				= NULL;

	this->InitValidFlags();

	short	type	= ::GS_GetObjectType( gCBP, fhObject );
	if ( type == kParametricNode ) {
		RecordHandle	hParmRecord	= NULL;
		FormatHandle	hParmFormat	= NULL;
		if ( ::GetCustomObjectDefinition( gCBP, fhObject, hParmRecord, hParmFormat ) ) {
			fhFormat		= hParmFormat;
			fhRecord		= hParmRecord;
		}
	}
	else {
		fhFormat		= ::GS_GetNamedObject( gCBP, TXString("ObjectWithWidgets") );
		fhRecord		= NULL;
	}

	return fhFormat != NULL;
}

MCObjectHandle CObjectWithWidgetsObjectData::GetDataObject() const
{
	return fhObject ? fhObject : fhFormat;
}

long CObjectWithWidgetsObjectData::GetUserData() const
{
	return (long) fpUserData;
}

SObjectWithWidgetsData& CObjectWithWidgetsObjectData::GetData()
{
	// the user data should be set here
	ASSERTN( kEveryone, fpUserData );
	return *fpUserData;
}

TXString CObjectWithWidgetsObjectData::GetText()
{
	if ( ! fTextValid ) {
		char*		szText		= NULL;
		size_t		textSize	= 0;

		if ( fhRecord ) {
			TRecordHandler	record( fhRecord );
			TFormatHandler	format( fhFormat );	
			TRecordItem		textItem( format.GetFieldStyle( kTextParamIndex ) );
			if ( record.GetFieldObject( kTextParamIndex, textItem ) ) {
				textItem.GetFieldValue( szText, textSize );
				fText	= TXString( szText, textSize );

				fTextValid		= true;
			}
		}
		else if ( fhFormat ) {
			TFormatHandler	format( fhFormat );	
			TRecordItem		textItem( format.GetFieldStyle( kTextParamIndex ) );
			if ( format.GetFieldDefault( kTextParamIndex, textItem ) ) {
				textItem.GetFieldValue( szText, textSize );
				fText	= TXString( szText, textSize );

				fTextValid		= true;
			}
		}
	}

	return fText;
}

bool CObjectWithWidgetsObjectData::GetUseCustomText()
{
	if ( ! fUseCustomTextValid ) {
		if ( fhRecord ) {
			TRecordHandler	record( fhRecord );
			TFormatHandler	format( fhFormat );	
			TRecordItem		booleanItem( format.GetFieldStyle( kUseCustomTextParamIndex ) );
			if ( record.GetFieldObject( kUseCustomTextParamIndex, booleanItem ) ) {
				Boolean	value;
				booleanItem.GetFieldValue( value );
				fUseCustomText	= value ? true : false;
			}
		}
		else if ( fhFormat ) {
			TFormatHandler	format( fhFormat );	
			TRecordItem		booleanItem( format.GetFieldStyle( kUseCustomTextParamIndex ) );
			if ( format.GetFieldDefault( kUseCustomTextParamIndex, booleanItem ) ) {
				Boolean	value;
				booleanItem.GetFieldValue( value );
				fUseCustomText	= value ? true : false;
			}
		}
	}

	return fUseCustomText;
}

void CObjectWithWidgetsObjectData::SetPopupText(const TXString& text)
{
	fPopupTextValid	= true;
	fPopupText		= text;

	if ( fhRecord ) {
		TRecordHandler	rh( fhRecord );
		TRecordItem		recItem( rh.GetFieldStyle( kPopupIndex ) );
		if ( rh.GetFieldObject( kPopupIndex, recItem ) ) {
			const char* szText		= fPopupText;
			size_t		textLen		= fPopupText.GetLength();

			if ( recItem.SetFieldValue( szText, textLen ) ) {
				rh.SetFieldObject( kPopupIndex, recItem );
			}
		}
	}
	else {
		TFormatHandler	format( fhFormat );	
		TRecordItem		recItem( format.GetFieldStyle( kPopupIndex ) );
		if ( format.GetFieldDefault( kPopupIndex, recItem ) ) {
			const char* szText		= fPopupText;
			size_t		textLen		= fPopupText.GetLength();

			if ( recItem.SetFieldValue( szText, textLen ) ) {
				format.SetFieldDefault( kPopupIndex, recItem );
			}
		}
	}
}

TXString CObjectWithWidgetsObjectData::GetPopupText()
{
	if ( ! fPopupTextValid ) {
		char*		szText		= NULL;
		size_t		textSize	= 0;

		if ( fhRecord ) {
			TRecordHandler	record( fhRecord );
			TFormatHandler	format( fhFormat );	
			TRecordItem		textItem( format.GetFieldStyle( kPopupIndex ) );
			if ( record.GetFieldObject( kPopupIndex, textItem ) ) {
				textItem.GetFieldValue( szText, textSize );
				fPopupText		= TXString( szText, textSize );

				fPopupTextValid	= true;
			}
		}
		else if ( fhFormat ) {
			TFormatHandler	format( fhFormat );	
			TRecordItem		textItem( format.GetFieldStyle( kPopupIndex ) );
			if ( format.GetFieldDefault( kPopupIndex, textItem ) ) {
				textItem.GetFieldValue( szText, textSize );
				fPopupText		= TXString( szText, textSize );

				fPopupTextValid	= true;
			}
		}
	}

	return fPopupText;
}

TXString CObjectWithWidgetsObjectData::GetNormalPopupText()
{
	if ( ! fNormalPopupTextValid ) {
		char*		szText		= NULL;
		size_t		textSize	= 0;

		if ( fhRecord ) {
			TRecordHandler	record( fhRecord );
			TFormatHandler	format( fhFormat );	
			TRecordItem		textItem( format.GetFieldStyle( kNormalPopupIndex ) );
			if ( record.GetFieldObject( kNormalPopupIndex, textItem ) ) {
				textItem.GetFieldValue( szText, textSize );
				fNormalPopupText		= TXString( szText, textSize );

				fNormalPopupTextValid	= true;
			}
		}
		else if ( fhFormat ) {
			TFormatHandler	format( fhFormat );	
			TRecordItem		textItem( format.GetFieldStyle( kNormalPopupIndex ) );
			if ( format.GetFieldDefault( kNormalPopupIndex, textItem ) ) {
				textItem.GetFieldValue( szText, textSize );
				fNormalPopupText		= TXString( szText, textSize );

				fNormalPopupTextValid	= true;
			}
		}
	}

	return fNormalPopupText;
}