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



#include "VWPluginToolApp.h"

#include "VWPluginToolProviders.h"

long									ToolMain(long action, long message1, long message2, long &userData);
VWFC::PluginSupport::VWPluginToolApp*	CreateToolInstance();


#ifndef VWFC_NO_PLUGINMAIN


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


extern "C" long GS_EXTERNAL_ENTRY plugin_main(long action, long message1, long message2, long& userData, CallBackPtr cbpParam)
{
	using namespace VWFC::MemoryManager;

	GSExternalSetup(cbpParam);

    // initialize VCOM mechanizm
    ::GS_InitializeVCOM( gCBP );

	long reply	= 0;

	{ // SCOPE
		// Init gSDK
		VCOMPtr<VectorWorks::ISDK> localSDKPtr(VectorWorks::IID_SDK);
		gSDK = localSDKPtr;

		// create the memory namagers
		// and verify their presents
		VWFC::MemoryManager::MManager* pOldManager		= NULL;
		VWFC::MemoryManager::MManager* pOldVWManager	= NULL;
		VWFC::AllocateMemoryManagers( & pOldManager, & pOldVWManager );

		VWFC_VERIFY( VWFC::GetMManager() != NULL && VWFC::GetVWMManager() != NULL );
		if ( VWFC::GetMManager() != NULL && VWFC::GetVWMManager() != NULL ) {
			struct SToolInnerData {
				long			fUserData;
				long			farrCustomBarRefIDs[ 10 ];
			};

			SToolInnerData*		pInnerData		= (SToolInnerData*) userData;
			if ( action == kToolInitGlobals ) {
				pInnerData				= NEW_VW_OBJECT( SToolInnerData );
				pInnerData->fUserData	= 0;
				memset( pInnerData->farrCustomBarRefIDs, 0, sizeof(pInnerData->farrCustomBarRefIDs) );
			}

			VWFC_ASSERT( pInnerData );
			if ( pInnerData ) {
				// init custom bars
				VWFC::PluginSupport::VWPluginToolCustomBar::SetCustomBars( pInnerData->farrCustomBarRefIDs, 10 );

				////////////////////////////////////////////////////////////////////////
				// Call the object
				// call the user's main function
#ifndef _DEBUG
				try {
#endif
				// call the user's main function
				reply = ToolMain(action, message1, message2, pInnerData->fUserData );
#ifndef _DEBUG
				}
				catch( ... ) {
					// ups, an error in the plug in
					VWFC_ASSERT( false );
				}
#endif
			}

			if ( action == kToolDisposeGlobals ) {
				DELETE_VW_OBJECT( SToolInnerData, pInnerData );
			}
			userData		= (long) pInnerData;

			// dump local memory leaks
			if ( VWFC::GetMManager() ) {
				VWFC::GetMManager()->DumpMemory( PLUGIN_NAME );
			}
		}

		// release the memory managers
		VWFC::FreeMemoryManagers( pOldManager, pOldVWManager );
	}

	GSExternalSetdown(0L);
	return reply;
};

#endif	// VWFC_NO_PLUGINMAIN

// ------------------------------------------------------------------------------------------------------------------
long ToolMain(long action, long message1, long message2, long &userData)
{
	long	reply	= kToolEventHandled;

	using namespace VWFC::PluginSupport;

	// allocate the application
	VWPluginToolApp*	pApp	= ::CreateToolInstance();

	VWFC_ASSERT( pApp );
	if ( pApp ) {
		pApp->SetUserData( userData );
		pApp->SetResult( kToolEventHandled );

		//DMSG(( kVStanev, "VWFC::ToolMain: action=%d\n", action ));
		CModeBarProvider	modeBarProvider;
		pApp->SetToolModeBarProvider( & modeBarProvider );

		switch (action) {
			case kToolInitGlobals:
				reply	= pApp->InitializeApp() ? pApp->GetResult() : kToolCouldNotInitialize;
				break;

			case kToolDisposeGlobals:
				pApp->DeinitializeApp();
				break;

			case kToolDoSetup: {
					CModeBarInitProvider	modeBarInitProvider;

					reply	= pApp->DoSetUp( message1 == kSetupSetdownPauseRestoreFlag, & modeBarInitProvider ) ? pApp->GetResult() : kToolCouldNotSetUp;
				} break;

			case kToolDoSetDown: {
					CModeBarInitProvider	modeBarInitProvider;

					pApp->DoSetDown( message1 == kSetupSetdownPauseRestoreFlag, & modeBarInitProvider );
					reply	= pApp->GetResult();
				} break;

			case kToolDoDrawScrMod:
				pApp->DoDrawScrMod();
				reply	= pApp->GetResult();
				break;

			case kToolDoUndrawScrMod:
				pApp->DoUndrawScrMod();
				reply	= pApp->GetResult();
				break;

			case kOnToolInitXProperties: {
					CToolPropertiesProvider		propsProvider( message1 );

					pApp->OnInitXProperties( & propsProvider );
					reply	= pApp->GetResult();
				} break;

			case kToolSelectionChange:
				pApp->OnSelectionChange();
				reply	= pApp->GetResult();
				break;

			case kToolCustomBarEvent: {
					CustomBarEventData* pEventData = (CustomBarEventData*) message1;
					if ( pEventData ) {
						switch( pEventData->fCustomBarEventSelector ) {
							case kCustomBarSetup:
								pApp->OnCustomBar_Setup();
								break;
							case kCustomBarSetdown:
								pApp->OnCustomBar_Setdown();
								break;
							case kCustomBarUpdateValues:
								pApp->OnCustomBar_UpdateValues();
								break;
							case kCustomBarLockValue: {
								CustomBarLockValueData* pLockData = (CustomBarLockValueData*) pEventData->fData;
								if ( pLockData ) {
									pApp->OnCustomBar_LockValue( pLockData->fFieldIndex, pLockData->fUserLockString );
								}
							}break;
							case kCustomBarUnlockValue:
								pApp->OnCustomBar_UnlockValue( pEventData->fData );
								break;
						}
					}
					reply	= pApp->GetResult();
				} break;

			case kToolGetCursor:
				reply	= pApp->GetCursor();
				break;

			case kToolGetStatus: {
					CStatusProvider	statusProvider;

					reply	= pApp->GetStatus( & statusProvider );
				} break;

			case kToolPointAdded:
				pApp->PointAdded();
				reply	= pApp->GetResult();
				break;

			case kToolPointRemoved:
				pApp->PointRemoved( message1 == kClearingAllToolPoints );
				reply	= pApp->GetResult();
				break;

			case kToolDraw: {
					CDrawProvider	drawProvider;
					pApp->Draw( & drawProvider);
					reply	= pApp->GetResult();
				} break;

			case kToolMouseMove:
				pApp->MouseMove();
				reply	= pApp->GetResult();
				break;

			case kToolHandleComplete:
				pApp->HandleComplete();
				reply	= pApp->GetResult();
				break;

//			case kToolDoInterface:		// DEPRECATED
//				pApp->DoInterface( VWPoint2D( * ((WorldPt*)message1) ) );
//				break;

			case kToolDoModeEvent: {
					size_t		groupID		= message1 > 0 ? (size_t)(message1-1) : 0;
					size_t		buttonID	= message2 > 0 ? (size_t)(message2-1) : 0;
					size_t		newButtonID	= buttonID & 0x0000FFFF;
					size_t		oldButtonID	= (buttonID & 0xFFFF0000) >> 24;

					pApp->DoModeEvent( groupID, newButtonID, oldButtonID );
					reply	= pApp->GetResult();
				} break;

			case kToolDoDoubleClick:
				pApp->DoDoubleClick();
				reply	= pApp->GetResult();
				break;

			case kToolDrawingDoubleClick:
				pApp->SetResult( kToolSwitchToCursor );
				reply	= pApp->DrawingDoubleClick() ? kToolCompleted : pApp->GetResult();
				break;

			case kToolGenericStateChange:
				pApp->GenericStateChange();
				break;

#ifndef _VWFC_FOR_VW125x
			case kToolDisplayContextualHelp: {
					TXString	contextualHelpID	= pApp->GetContextualHelpID();
					if ( ! contextualHelpID.IsEmpty() ) {
						if ( ::GS_DisplayContextualHelp( gCBP, contextualHelpID ) ) {
							reply = kToolHasContextualHelp;
						}
						else if ( contextualHelpID.GetAt(0) == '-' || contextualHelpID.GetAt(0) == '_' || contextualHelpID.GetAt(0) == '.' ) {
							// the plug-in doesn't suply help ID
							// dont consider that problem
							reply = kMenuItemHasContextualHelp;
						}
					}
				} break;
#endif
				case kToolInitByObject: {
					MCObjectHandle			hTheObject	= (MCObjectHandle) message1;
					CModeBarInitProvider	modeBarInitProvider;

					pApp->OnToolInitByObject( hTheObject, & modeBarInitProvider );
				} break;
			default:
				reply = pApp->OnDefaultEvent( action, message1, message2 );
				break;
		}

		userData	= pApp->GetUserData();

		// free the application definition
		pApp->~VWPluginToolApp();
		free( pApp );
		pApp		= NULL;
	}

	return reply;
}