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



#include "VWPluginLibraryArgTable.h"
#include "VWPluginLibraryApp.h"
#include "VWPluginLibraryRoutine.h"

using namespace VWFC::PluginSupport;

// predefine these hidden memory managment functions
namespace VWFC
{
	bool	HasAllocatedMemroyManagers();
	void	AllocateMemoryManagers(VWFC::MemoryManager::MManager** ppOutOldManager, VWFC::MemoryManager::MManager** ppOutOldVWManager);
	void	FreeMemoryManagers(VWFC::MemoryManager::MManager* pOldManager, VWFC::MemoryManager::MManager* pOldVWManager);
}

// this is defined by the plug-in library app file
// using macro 'INSTANTIATE_PLUGINLIBRARY_APP' defiend in VWPluginLibraryApp.h
extern VWFC::PluginSupport::VWPluginLibraryApp		g_varLibApp;

// MainEntry_Library
extern "C" long GS_EXTERNAL_ENTRY plugin_main(long routineSelector, void* inArgTable, long &userData, CallBackPtr cbpParam)
{
	GSExternalSetup(cbpParam);

#ifndef _VWFC_FOR_VW125x
    // initialize VCOM mechanizm
    ::GS_InitializeVCOM( gCBP );
#endif

	long reply	= 0;

	{ // SCOPE
		// Init gSDK
		VCOMPtr<VectorWorks::ISDK> localSDKPtr(VectorWorks::IID_SDK);
		gSDK = localSDKPtr;
		
		// create the memory namagers
		// and verify their presents
		bool		bMMgrCreated	= VWFC::HasAllocatedMemroyManagers();
		if ( ! bMMgrCreated ) {
			VWFC::AllocateMemoryManagers( NULL, NULL );
		}

#ifndef _DEBUG
		try
		{
#endif
			if ( routineSelector == kVCOMRegisterInterfaces ) {
				reply	= g_varLibApp.RegisterInterfaces( inArgTable );
			}
			else if ( routineSelector == kVCOMQueryInterface ) {
				VWIID*        pIID         = (VWIID*) inArgTable;
				IVWUnknown*   pInterface   = 0;
				if ( pIID == NULL ) {
					reply = kVCOMError_InvalidArg;
				}
				else {
					reply                    = kVCOMError_NoInstance;
					g_varLibApp.CreateInterfaceInstance( *pIID, & pInterface );
				}

				if ( pInterface )
					reply             = kVCOMError_NoError;

				userData        = (long) pInterface;			
			}
			else if ( routineSelector == kVCOMReleaseInterface ) {
				VWIID*        pIID        = (VWIID*) inArgTable;
				IVWUnknown*   pInterface  = (IVWUnknown*) userData;
				if ( pInterface == NULL || pIID == NULL ) {
					reply = kVCOMError_InvalidArg;
				}
				else {
					reply                    = kVCOMError_NoError;
					g_varLibApp.DeleteInterfaceInstance( *pIID, pInterface );
				}
			}
			else {
				PluginLibraryArgTable*		pArgTable = static_cast<PluginLibraryArgTable*>( inArgTable );
				VWPluginLibraryArgTable		argTable( pArgTable );

				reply	= g_varLibApp.DispatchRoutine( routineSelector, argTable, userData );
			}
#ifndef _DEBUG
		}
		catch( ... ) {
			// ups, an error in the plug in
			VWFC_ASSERT( false );
		}
#endif

		static long	sRefCnt		= 0;

		if ( routineSelector == kPluginLIBInitGlobals ) {
			if ( reply & kAddCodeReference ) {
				sRefCnt++;
			}
		}
		else if ( routineSelector == kPluginLIBDisposeGlobals ) {
			if ( sRefCnt > 0 ) {
				sRefCnt--;
			}
		}

		if ( sRefCnt == 0 ) {
			// dump local memory leaks
			if ( VWFC::GetMManager() ) {
				VWFC::GetMManager()->DumpMemory( PLUGIN_NAME );
			}
			
			// release the memory managers
			VWFC::FreeMemoryManagers( NULL, NULL );
		}
	}

	GSExternalSetdown(0L);

	return reply;
}
