/*
	File:		CEnvelopeInfo.10.1.cpp

	Contains:	C++ implementation of EnvelopeInfo pointers to Envelopes.

	Copyright:	© 2003 by Apple Computer, Inc., all rights reserved.

 	NOT_FOR_OPEN_SOURCE <to be reevaluated at a later time>

	Change History:

		$Log: CEnvelopeInfo.10.1.cpp,v $
		Revision 1.2  2003/07/22 18:43:10  dasenbro
		Mark messages that have been migrated.
		
		Revision 1.1  2003/04/20 23:46:10  dasenbro
		Initial check-in.
		
	
	Projector History:

	To Do:
*/


#include <time.h>

#include "CEnvelopeInfo.10.1.h"
#include "CMailSpool.10.1.h"
#include "CEnvelope.10.1.h"
#include "CMailDatabase.10.1.h"
#include "CUtils.h"
#include "CGlobals.h"


extern CMailDatabase_10_1	*gDB;	// From CAppServer.cpp

Boolean	CEnvelopeInfo_10_1::GetSetFields	(const eFieldDataRequest_10_1 inFieldRequest, const void *inObjDataPtr, void *outFieldData)
{
	Boolean	result = false;
	CEnvInfoData_10_1	*theData		= (CEnvInfoData_10_1 *) inObjDataPtr;
	CEnvelopeInfo_10_1	*aTempObject	= NULL;
	ObjID			*anObjIDPtr		= (ObjID *) outFieldData;

	switch (inFieldRequest)
	{
		case kSetObjID_10_1:
			if (theData != NULL)
			{
				theData->fEnvelopeInfoID = *anObjIDPtr;
			}
			break;
			
		case k2ndIDRequest_10_1:
			if (theData != NULL)
			{
				if (theData->fMailSpoolID != 0)
				{
					*anObjIDPtr = theData->fMailSpoolID;
					result = true;
				}
			}
			break;

		case kObjectPINGRequest_10_1:
			// cause the objects constructor to get called, so we force a check of
			// the struct alignment...
			aTempObject = new CEnvelopeInfo_10_1;
			delete aTempObject;
			break;

		case k2ndIDTargetChk_10_1:
			// fall through...
			
		case kStringNameRequest_10_1:
		default:
			result = false;
			break;
	}
	
	return result;
}


ObjID CEnvelopeInfo_10_1::GetObjectID	( void )
{
	return fEnvInfoData.fEnvelopeInfoID;
}

//--------------------------------------------------------------------------------------------------
//	 Done
//
//--------------------------------------------------------------------------------------------------

void CEnvelopeInfo_10_1::Done ( CEnvelopeInfo_10_1* &inPtr )
{
	CDBBaseObject_10_1 *aDBObject = (CDBBaseObject_10_1 *) inPtr;
	aDBObject->Done(aDBObject);

	inPtr = (CEnvelopeInfo_10_1 *)aDBObject;
}


CDBBaseObject_10_1 * CEnvelopeInfo_10_1::ObjectAllocNew	( void )
{
	return new CEnvelopeInfo_10_1;
}

CEnvelopeInfo_10_1* CEnvelopeInfo_10_1::FindByID ( const ObjID inObjectID )
{
	return (CEnvelopeInfo_10_1 *) CDBMailBaseObject_10_1::MailUniversalFindByID(	inObjectID,
														CEnvelopeInfo_10_1::GetObjTypeConstant(),
														CEnvelopeInfo_10_1::GetObjVersConstant(),
														CEnvelopeInfo_10_1::GetObjSizeConstant(),
														CEnvelopeInfo_10_1::ObjectAllocNew		);
} // FindByID





CEnvelopeInfo_10_1* CEnvelopeInfo_10_1::FindBySpoolEnvelope (ObjID inMailSpoolID, ObjID inEnvelopeID)
{
	if ((inMailSpoolID == 0) || (inEnvelopeID == 0))
	{
		return (NULL);
	}
	
	SDBIterator_10_1	*theIterator = NULL;
	ObjID				theEnvInfoID;
	CEnvelopeInfo_10_1	*theEnvInfo = NULL;
	CMailSpool_10_1			*theMailSpool = NULL;
	
	
	theMailSpool = CMailSpool_10_1::FindByID(inMailSpoolID);
	if (theMailSpool != NULL)
	{
		theIterator = theMailSpool->GetEnvelopeInfoIterator();

		while (gDB->NextObject(theIterator, theEnvInfoID) == kNoErr)
		{
			theEnvInfo = CEnvelopeInfo_10_1::FindByID(theEnvInfoID);
			if (theEnvInfo != NULL)
			{
				if (theEnvInfo->GetEnvelopeID() == inEnvelopeID)
				{
					break;
				}
				
				theEnvInfo->Done(theEnvInfo);
			}
		}
		theMailSpool->ReleaseEnvelopeInfoIterator(theIterator);
	}
	
	
	return theEnvInfo;
}


CEnvelopeInfo_10_1* CEnvelopeInfo_10_1::Create (	ObjID	 inMailSpoolID,
										ObjID	 inEnvelopeID,
										uInt32	 inMsgSize )
{
	CEnvelopeInfo_10_1* theEnvelopeInfo = new CEnvelopeInfo_10_1;
	OSErr	result;
	ObjID	aNewID;
	
	try
	{
		ThrowIfMemFail_ (theEnvelopeInfo);
		
		(gDB->GetBaseObjectCachePtr())->LockTheCache(CEnvelopeInfo_10_1::GetObjTypeConstant());
		
		result = gDB->CreateObj(CEnvelopeInfo_10_1::GetObjTypeConstant(), aNewID, theEnvelopeInfo->GetEnvInfoData());
		if ( result == CMailDatabase_10_1::kDBNoErr )
		{
			theEnvelopeInfo->Use();
			theEnvelopeInfo->SetMailSpoolID(inMailSpoolID);
			theEnvelopeInfo->SetEnvelopeID(inEnvelopeID);
			theEnvelopeInfo->SetMsgSize(inMsgSize);	
			theEnvelopeInfo->SetDirty();
		}
		else
		{
			delete theEnvelopeInfo;
			theEnvelopeInfo = NULL;
		}
			
		(gDB->GetBaseObjectCachePtr())->UnLockTheCache(CEnvelopeInfo_10_1::GetObjTypeConstant());
	}
	catch ( ExceptionCode err )
	{
	}
	
	return (theEnvelopeInfo);
}

Boolean CEnvelopeInfo_10_1::Delete(CEnvelopeInfo_10_1* inEnvelopeInfo)
{
	OSErr	result;
	// Note: This method should only _ever_ be called from CMailSpool_10_1::Remove()
	//       We do not remove references to CEnvelopes here.

	Boolean deleted = false;
	
	try
	{
		if (inEnvelopeInfo != NULL)
		{
			(gDB->GetBaseObjectCachePtr())->LockTheCache(CEnvelopeInfo_10_1::GetObjTypeConstant());

			result = gDB->RemoveObj(CEnvelopeInfo_10_1::GetObjTypeConstant(), inEnvelopeInfo->GetEnvelopeInfoID());
			deleted = (result == kNoErr);
			if (deleted)
			{
				inEnvelopeInfo->fEnvInfoData.fEnvelopeInfoID = 0;
			}
			
			(gDB->GetBaseObjectCachePtr())->UnLockTheCache(CEnvelopeInfo_10_1::GetObjTypeConstant());
		}
	}
	catch ( ExceptionCode err )
	{
		(gDB->GetBaseObjectCachePtr())->UnLockTheCache(CEnvelopeInfo_10_1::GetObjTypeConstant());
	}

	return (deleted);
}

uInt32 CEnvelopeInfo_10_1::Count(void)
{
	OSErr result;
	uInt32 aCount = 0;
	result = gDB->GetObjectCount (CEnvelopeInfo_10_1::GetObjTypeConstant(), aCount);	// of ourselves
	if (result != kNoErr)
	{
		aCount = 0;
	}
	
	return aCount;
}

#pragma mark -

CEnvelopeInfo_10_1::CEnvelopeInfo_10_1 ( void ) :
	CDBMailBaseObject_10_1(	&fEnvInfoData.fDBHeader,
				&fEnvInfoData.fDBFooter,
				&fEnvInfoData,
				CEnvelopeInfo_10_1::GetObjTypeConstant(),
				CEnvelopeInfo_10_1::GetObjVersConstant(),
				CEnvelopeInfo_10_1::GetObjSizeConstant() )
{
	fEnvInfoData.fEnvelopeInfoID	 = 0;
	fEnvInfoData.fMailSpoolID		 = 0;
	fEnvInfoData.fEnvelopeID		 = 0;
	fEnvInfoData.fSeenTime			 = 0;
	fEnvInfoData.fMessageSize		 = 0;	
	fEnvInfoData.fEnvInfoWarningTime = 0;	
	fEnvInfoData.fFlags				 = 0;

	// Reserved
	fEnvInfoData.fUID				= 0;
	fEnvInfoData.fReserved2			= kReservedConst;

	this->ChkCompilerStructAlignment();
} // CEnvelopeInfo_10_1



CEnvelopeInfo_10_1::~CEnvelopeInfo_10_1 ( void )
{
}

#pragma mark -

ObjID CEnvelopeInfo_10_1::GetEnvelopeInfoID(void)
{
	return (fEnvInfoData.fEnvelopeInfoID);
}

ObjID CEnvelopeInfo_10_1::GetMailSpoolID ( void )
{
	return( fEnvInfoData.fMailSpoolID );
}

void CEnvelopeInfo_10_1::SetDirty ( void )
{
	if ((this != NULL) && (this->GetEnvelopeInfoID() != 0))
	{
		this->setDirty();
	}
}

CEnvInfoData_10_1* CEnvelopeInfo_10_1::GetEnvInfoData ( void )
{
	if (this != NULL)
	{
		return( &fEnvInfoData );
	}

	return( NULL );
}

uInt32 CEnvelopeInfo_10_1::GetMigrationFlag ( void )
{
	return ( fEnvInfoData.fReserved2 );
}

void CEnvelopeInfo_10_1::SetMigrationFlag( uInt32 inMigrationFlag )
{
	if ( fEnvInfoData.fReserved2 != inMigrationFlag )
	{
		fEnvInfoData.fReserved2 = inMigrationFlag;
		this->SetDirty();
	}
}

void CEnvelopeInfo_10_1::SetMailSpoolID(ObjID inMailSpoolID)
{
	// the MailSpool ID is used as a CMailDatabase_10_1 2nd-ID object.  We need to flush
	// this through to the mail db immediately so that any iteration that is
	// going on will reflect the proper list iteration...
	// if you don't understand why this is important you don't understand the
	// Mail server's DB & our caching code and you shouldn't be changing it.
	
	if (fEnvInfoData.fMailSpoolID != inMailSpoolID)
	{
		(gDB->GetBaseObjectCachePtr())->LockTheCache( CEnvelopeInfo_10_1::GetObjTypeConstant() );
		fEnvInfoData.fMailSpoolID = inMailSpoolID;
		this->SetDirty();
		this->setDirty(true);
		(gDB->GetBaseObjectCachePtr())->UnLockTheCache( CEnvelopeInfo_10_1::GetObjTypeConstant() );
	}
}

ObjID CEnvelopeInfo_10_1::GetEnvelopeID(void)
{
	return (fEnvInfoData.fEnvelopeID);
}

void CEnvelopeInfo_10_1::SetEnvelopeID(ObjID inEnvelopeID)
{
	if (fEnvInfoData.fEnvelopeID != inEnvelopeID)
	{
		fEnvInfoData.fEnvelopeID = inEnvelopeID;
		this->SetDirty();
	}
}

ObjID CEnvelopeInfo_10_1::GetUID ( void )
{
	return( fEnvInfoData.fUID );
} // GetUID


void CEnvelopeInfo_10_1::SetUID ( uInt32 inUID )
{
	if ( fEnvInfoData.fUID != inUID )
	{
		fEnvInfoData.fUID = inUID;
		this->SetDirty();
	}
} // SetUID

#pragma mark -

uInt32 CEnvelopeInfo_10_1::GetMsgSize(Boolean inIncludeStatus)
{
	if (inIncludeStatus)
	{
		if (this->IsPOP3Read())
			return (fEnvInfoData.fMessageSize + 11);		// length of "Status: R"<CR><LF>
	}

	return (fEnvInfoData.fMessageSize);
}

void CEnvelopeInfo_10_1::SetMsgSize(uInt32 inMsgSize)
{
	if (fEnvInfoData.fMessageSize != inMsgSize)
	{
		fEnvInfoData.fMessageSize = inMsgSize;
		this->SetDirty();
	}
}

uInt32 CEnvelopeInfo_10_1::GetFlags(void)
{
	return (fEnvInfoData.fFlags);
}

void CEnvelopeInfo_10_1::SetFlags ( uInt32 inFlags )
{
	CMailSpool_10_1	*pMailSpool	= nil;

	// Set the envelope info flags
	if ( fEnvInfoData.fFlags != inFlags )
	{
		// Get this envelopes Mail Spool
		pMailSpool = CMailSpool_10_1::FindByID( this->GetMailSpoolID() );
		if ( pMailSpool != nil )
		{
			// Going from Seen to Unseen
			if ( (fEnvInfoData.fFlags & kIMAP4Seen) && (!(inFlags & kIMAP4Seen)) )
			{
				pMailSpool->IncrementUnseenCount();
			}
			// Unseen to Seen
			else if ( (!(fEnvInfoData.fFlags & kIMAP4Seen)) && (inFlags & kIMAP4Seen) )
			{
				pMailSpool->DecrementUnseenCount();
			}

			pMailSpool->Done( pMailSpool );
		}

		// Has it already been seen
		if ( fEnvInfoData.fFlags & kIMAP4Seen )
		{
		}

		fEnvInfoData.fFlags = inFlags;
		if ( fEnvInfoData.fFlags & kIMAP4Seen )
		{
			if ( this->GetSeenTime() == 0 )
			{
				SetSeenTime( ::time( nil ) );
			}
		}
		this->SetDirty();
	}
}

uInt32 CEnvelopeInfo_10_1::GetEnvInfoWarnTime(void)
{
	return (fEnvInfoData.fEnvInfoWarningTime);
}

void CEnvelopeInfo_10_1::SetEnvInfoWarnTime(const uInt32 inWarnTime)
{
	if (fEnvInfoData.fEnvInfoWarningTime != inWarnTime)
	{
		fEnvInfoData.fEnvInfoWarningTime = inWarnTime;
		this->SetDirty();
	}
}

uInt32 CEnvelopeInfo_10_1::GetSeenTime ( void )
{
	return ( fEnvInfoData.fSeenTime );
}

void CEnvelopeInfo_10_1::SetSeenTime ( const uInt32 inValue )
{
	if ( fEnvInfoData.fSeenTime != inValue )
	{
		fEnvInfoData.fSeenTime = inValue;
		this->SetDirty();
	}
}

#pragma mark -

Boolean CEnvelopeInfo_10_1::IsPOP3Read(void)
{
	return ((fEnvInfoData.fFlags & kPOP3Read) != 0);
}

Boolean CEnvelopeInfo_10_1::IsPOP3Deleted(void)
{
	return ((fEnvInfoData.fFlags & kPOP3Deleted) != 0);
}

void CEnvelopeInfo_10_1::SetPOP3Read ( Boolean inValue )
{
	if ( inValue == true )
	{
		fEnvInfoData.fFlags |= kPOP3Read;
		if ( this->GetSeenTime() == 0 )
		{
			SetSeenTime( ::time( nil ) );
		}
	}
	else
	{
		fEnvInfoData.fFlags &= ~kPOP3Read;
	}
	this->SetDirty();
}

void CEnvelopeInfo_10_1::SetPOP3Deleted(Boolean inValue)
{
	if (inValue == true)
		fEnvInfoData.fFlags |= kPOP3Deleted;
	else
		fEnvInfoData.fFlags &= ~kPOP3Deleted;

	this->SetDirty();
}

#pragma mark -

uInt32 CEnvelopeInfo_10_1::GetMessageSize(Boolean inIncludeStatus)
{
	return (this->GetMsgSize(inIncludeStatus));
}

#pragma mark -

// ---------------------------------------------------------------------------
//		* CEnvelopeInfo_10_1 LogExpiration
//
//			Log expiration message  
// ---------------------------------------------------------------------------

