//
//	Copyright © 2006 Nemetschek North America 
//	All Rights Reserved.
//
// Created by Vladislav Stanev

#include "StdAfx.h"
//#include "VWRecordObj.h"

using namespace VWFC::Tools;
using namespace VWFC::VWObjects;

VWRecordObj::VWRecordObj(MCObjectHandle hRecordHandle)
{
	fhObject		= hRecordHandle;

	VWFC_ASSERT( VWRecordObj::IsRecordObject( fhObject ) );
	if ( ! VWRecordObj::IsRecordObject( fhObject ) )
		THROW_VWFC_EXCEPTION( VWBadObjectTypeException, 0, "bad handle type when creating" );
}

// bUseExistingRecord	- true then use the record in hObject of format hFormat if it exist - otherwise create record
//						- false then always crete record object from the hFormat inside hObject
VWRecordObj::VWRecordObj(MCObjectHandle hFormat, MCObjectHandle hObject, bool bUseExistingRecord)
{
	if ( hFormat == NULL ) {
		THROW_VWFC_EXCEPTION( VWBadObjectTypeException, 0, "bad format handle type when creating" );
	}
	else {
		MCObjectHandle		hRecord	= NULL;
		if ( bUseExistingRecord ) {
			TFormatHandler		fh( hFormat );
			hRecord						= fh.AttachRecordToObject( hObject ); 
		}
		else {
			MCObjectHandle	hDefaultRecord	= ::GS_FindAuxObject( gCBP, hFormat, kRecordNode );
			ASSERTN( kVStanev, hDefaultRecord );
			hRecord							= ::GS_DuplicateObject( gCBP, hDefaultRecord );
			::GS_AttachAuxObject( gCBP, hRecord, hObject );

			// find the last object in the AUX list
			MCObjectHandle	hLastObj	= NULL;
			MCObjectHandle	hNextObj	= hRecord;
			while( hNextObj ) {
				MCObjectHandle	hNextAux	= ::GS_NextObject( gCBP, hNextObj );
				hNextObj					= ::GS_NextAuxObject( gCBP, hNextAux, kRecordNode );
				if ( hNextObj )
					hLastObj	= hNextObj;
			}

			// attach this record at the end of the AUX list
			if ( hLastObj ) {
				::GS_InsertObjectAfter( gCBP, hRecord, hLastObj );
			}
		}

		fhObject					= hRecord;

		VWFC_ASSERT( VWRecordObj::IsRecordObject( fhObject ) );
		if ( ! VWRecordObj::IsRecordObject( fhObject ) )
			THROW_VWFC_EXCEPTION( VWBadObjectTypeException, 0, "bad handle type when creating" );
	}
}

VWRecordObj::VWRecordObj(const VWRecordObj& src)
{
	fhObject	= src.fhObject;
}

VWRecordObj::~VWRecordObj()
{
}

VWRecordObj& VWRecordObj::operator=(const VWRecordObj& src)
{
	fhObject	= src.fhObject;
	return *this;
}

TXString VWRecordObj::GetRecordName() const
{
	VWFC_ASSERT( fhObject );
	TRecordHandler	rh( fhObject );
	
	Str63 nameOfFormat;
	rh.GetNameOfFormat( nameOfFormat );

	return nameOfFormat;
}

bool VWRecordObj::IsParametric() const
{
	VWFC_ASSERT( fhObject );
	TRecordHandler	rh( fhObject );
	return rh.IsParametric() ? true : false;
}

void VWRecordObj::SetParametric(bool bIsParametric)
{
	VWFC_ASSERT( fhObject );
	TRecordHandler	rh( fhObject );
	rh.SetIsParametric( bIsParametric );
}

size_t VWRecordObj::GetParamsCount() const
{
	VWFC_ASSERT( fhObject );
	TRecordHandler	rh( fhObject );
	return (size_t) rh.GetNumOfFields();
}

TXString VWRecordObj::GetParamName(size_t paramIndex) const
{
	VWFC_ASSERT( fhObject );
	TRecordHandler	rh( fhObject );

	Str20	nameOfField;
	// NOTE! 'GetNameOfField' return 1 based value
	rh.GetNameOfField( DemoteTo<short>( kVStanev, paramIndex+1 ), nameOfField );
	return nameOfField;
}

size_t VWRecordObj::GetParamIndex(const TXString& paramName) const
{
	VWFC_ASSERT( fhObject );
	TRecordHandler	rh( fhObject );

	// NOTE! 'GetFieldIndex' return 1 based value
	int		index	= rh.GetFieldIndex( paramName );
	if ( index == 0 )
		return (size_t) -1;	// not found

	return (size_t) (index - 1);
}

EFieldStyle VWRecordObj::GetParamStyle(size_t paramIndex) const
{
	VWFC_ASSERT( fhObject );
	TRecordHandler	rh( fhObject );

	// NOTE! 'GetFieldStyle' return 1 based value
	return (EFieldStyle) rh.GetFieldStyle( DemoteTo<short>( kVStanev, paramIndex+1 ) );
}

TXString VWRecordObj::GetParamValue(size_t paramIndex) const
{
	VWFC_ASSERT( fhObject );
	TRecordHandler	rh( fhObject );

	// NOTE! itemIndex is expected from the SDK as 1 based value
	short			itemIndex	= DemoteTo<short>( kVStanev, paramIndex+1 );
	EFieldStyle		style		= (EFieldStyle) rh.GetFieldStyle( itemIndex );
	TRecordItem valueItem( style );
	Boolean			ok			= rh.GetFieldObject( itemIndex, valueItem );
	VWFC_ASSERT( ok );

	TXString	value;
	if ( style == kFieldText ) {
		char*		string		= NULL;
		size_t		len			= 0;

		if ( ok ) {
			valueItem.GetFieldValue( string, len );
			value	= TXString( string, len );
		}
	}
	else {
		Str255		theString;
		if ( valueItem.GetFieldValueAsString( theString ) ) {
			value	= theString;
		}
	}

	return value;
}

void VWRecordObj::SetParamValue(size_t paramIndex, const TXString& value)
{
	VWFC_ASSERT( fhObject );
	TRecordHandler	rh( fhObject );

	// NOTE! itemIndex is expected from the SDK as 1 based value
	short			itemIndex	= DemoteTo<short>( kVStanev, paramIndex+1 );
	EFieldStyle		style		= (EFieldStyle) rh.GetFieldStyle( itemIndex );
	TRecordItem		recItem( style );
	if ( VWFC_VERIFY( rh.GetFieldObject( itemIndex, recItem ) ) ) {
		if ( style == kFieldText ) {
			const char* szText		= value;
			size_t		textLen		= value.GetLength();

			if ( VWFC_VERIFY( recItem.SetFieldValue( szText, textLen ) ) ) {
				VWFC_VERIFY( rh.SetFieldObject( itemIndex, recItem ) );
			}
		}
		else {
			Str255		theString;
			value.CopyInto( theString );
			if ( VWFC_VERIFY( recItem.SetFieldValueAsString( theString ) ) ) {
				VWFC_VERIFY( rh.SetFieldObject( itemIndex, recItem ) );
			}
		}
	}
}


long VWRecordObj::GetParamLong(size_t paramIndex) const
{
	VWFC_ASSERT( fhObject );
	TRecordHandler	rh( fhObject );

	// NOTE! itemIndex is expected from the SDK as 1 based value
	short		itemIndex	= DemoteTo<short>( kVStanev, paramIndex+1 );
	TRecordItem valueItem( rh.GetFieldStyle( itemIndex ) );
	Boolean		ok			= rh.GetFieldObject( itemIndex, valueItem );
	VWFC_ASSERT( ok );

	long		value	= 0;
	if ( ok ) {
		valueItem.GetFieldValue( value );
	}

	return value;
}

void VWRecordObj::SetParamLong(size_t paramIndex, long value)
{
	VWFC_ASSERT( fhObject );
	TRecordHandler	rh( fhObject );

	// NOTE! itemIndex is expected from the SDK as 1 based value
	short			itemIndex	= DemoteTo<short>( kVStanev, paramIndex+1 );
	TRecordItem		recItem( rh.GetFieldStyle( itemIndex ) );
	if ( VWFC_VERIFY( rh.GetFieldObject( itemIndex, recItem ) ) ) {
		if ( VWFC_VERIFY( recItem.SetFieldValue( value ) ) ) {
			VWFC_VERIFY( rh.SetFieldObject( itemIndex, recItem ) );
		}
	}
}

bool VWRecordObj::GetParamBool(size_t paramIndex) const
{
	VWFC_ASSERT( fhObject );
	TRecordHandler	rh( fhObject );

	// NOTE! itemIndex is expected from the SDK as 1 based value
	short		itemIndex	= DemoteTo<short>( kVStanev, paramIndex+1 );
	TRecordItem valueItem( rh.GetFieldStyle( itemIndex ) );
	Boolean		ok			= rh.GetFieldObject( itemIndex, valueItem );
	VWFC_ASSERT( ok );

	Boolean		value	= 0;
	if ( ok ) {
		valueItem.GetFieldValue( value );
	}

	return value ? true : false;
}

void VWRecordObj::SetParamBool(size_t paramIndex, bool value)
{
	VWFC_ASSERT( fhObject );
	TRecordHandler	rh( fhObject );

	// NOTE! itemIndex is expected from the SDK as 1 based value
	short			itemIndex	= DemoteTo<short>( kVStanev, paramIndex+1 );
	TRecordItem		recItem( rh.GetFieldStyle( itemIndex ) );
	if ( VWFC_VERIFY( rh.GetFieldObject( itemIndex, recItem ) ) ) {
		Boolean		boolValue	= value;
		if ( VWFC_VERIFY( recItem.SetFieldValue( boolValue ) ) ) {
			VWFC_VERIFY( rh.SetFieldObject( itemIndex, recItem ) );
		}
	}
}

double VWRecordObj::GetParamReal(size_t paramIndex) const
{
	VWFC_ASSERT( fhObject );
	TRecordHandler	rh( fhObject );

	// NOTE! itemIndex is expected from the SDK as 1 based value
	short		itemIndex	= DemoteTo<short>( kVStanev, paramIndex+1 );
	TRecordItem valueItem( rh.GetFieldStyle( itemIndex ) );
	Boolean		ok			= rh.GetFieldObject( itemIndex, valueItem );
	VWFC_ASSERT( ok );

	double		value	= 0;
	if ( ok ) {
		valueItem.GetFieldValue( value );
	}

	return value;
}

void VWRecordObj::SetParamReal(size_t paramIndex, double value)
{
	VWFC_ASSERT( fhObject );
	TRecordHandler	rh( fhObject );

	// NOTE! itemIndex is expected from the SDK as 1 based value
	short			itemIndex	= DemoteTo<short>( kVStanev, paramIndex+1 );
	TRecordItem		recItem( rh.GetFieldStyle( itemIndex ) );
	if ( VWFC_VERIFY( rh.GetFieldObject( itemIndex, recItem ) ) ) {
		if ( VWFC_VERIFY( recItem.SetFieldValue( value ) ) ) {
			VWFC_VERIFY( rh.SetFieldObject( itemIndex, recItem ) );
		}
	}
}

TXString VWRecordObj::GetParamString(size_t paramIndex) const
{
	VWFC_ASSERT( fhObject );
	TRecordHandler	rh( fhObject );

	// NOTE! itemIndex is expected from the SDK as 1 based value
	short		itemIndex	= DemoteTo<short>( kVStanev, paramIndex+1 );
	TRecordItem valueItem( rh.GetFieldStyle( itemIndex ) );
	Boolean		ok		= rh.GetFieldObject( itemIndex, valueItem );
	VWFC_ASSERT( ok );

	TXString	value;
	char*		string		= NULL;
	size_t		len			= 0;

	if ( ok ) {
		valueItem.GetFieldValue( string, len );
		value	= TXString( string, len );
	}

	return value;
}

void VWRecordObj::SetParamString(size_t paramIndex, const TXString& value)
{
	VWFC_ASSERT( fhObject );
	TRecordHandler	rh( fhObject );

	// NOTE! itemIndex is expected from the SDK as 1 based value
	short			itemIndex	= DemoteTo<short>( kVStanev, paramIndex+1 );
	TRecordItem		recItem( rh.GetFieldStyle( itemIndex ) );
	if ( VWFC_VERIFY( rh.GetFieldObject( itemIndex, recItem ) ) ) {
		const char* szText		= value;
		size_t		textLen		= value.GetLength();

		if ( VWFC_VERIFY( recItem.SetFieldValue( szText, textLen ) ) ) {
			VWFC_VERIFY( rh.SetFieldObject( itemIndex, recItem ) );
		}
	}
}

bool VWRecordObj::IsRecordObject(MCObjectHandle hObj)
{
	short	type	= ::GS_GetObjectType( gCBP, hObj );
	return type == kRecordNode;
}