///////////////////////////////////////////////////////////////////////////////
/// @file deMachine.cpp
///
/// @brief System configuration analyzer
///
/// @author Lightning
///
/// This file is the intellectual property of Novus Delta, LLC.. Usage of the
/// contents of this file is subject to the Destiny3D Member License which
/// can be found at http://www.destiny3d.com.  Any other usage is prohibited.
///
/// This file is distributed "AS IS" without warranty of any kind.  Novus
/// Delta, LLC. does not guarantee the fitness of the contents of this file
/// for any particular purpose.
///
/// Copyright (C) 2001-2003 Novus Delta, LLC. All Rights Reserved.
///
/// <hr>
///                                 Change History
/// <hr>
///
/// @date Nov 2001
/// @author Lightning
/// @remarks Creation
///
///////////////////////////////////////////////////////////////////////////////


//=================================================================================
// Includes
//=================================================================================

#include <windows.h> // for DllMain
#include "deMachine.hpp"
#include "deMachineWindows.hpp"



//=================================================================================
// Local Function Prototypes
//=================================================================================

static deBoolean CreateMachine(void);
static deBoolean DestroyMachine(void);



//=================================================================================
// Machine Types
//
// These are the types of machine configurations currently supported. The values of 
// these strings are the possible values for parameter "MachineType" in the config
// file.  Except for bug fixes in the existing types, it would be a good idea to 
// create brand new types for anything new.  That will keep backward compatibility
// in tact.
//=================================================================================

char WindowsMachineType[] = "Windows";



//=================================================================================
// Global DLL Memory
//=================================================================================

IdeMachine *deMachine = NULL;
int deMachineProcessCount = 0;



//=================================================================================
// DllMain()
//
// Dll startup code.
//
// This is the entry point for other processes using the System Configuration Analyzer.
// This function gets called whenever another program does a LoadLibrary() on this
// DLL.  This keeps a reference counter (deMachineProcessCount) of the number of
// processes currently connected to this instance of the DLL.  When this DLL is 
// first loaded, it creates the machine object based on what info it gets from the
// Destiny config file.  Once the reference count goes to zero, the machine object
// is destroyed. 
//=================================================================================

BOOL WINAPI IdeMachine_DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
	lpvReserved = hinstDLL = 0;
	if (fdwReason == DLL_PROCESS_ATTACH)
	{
		deMachineProcessCount++;
		
		if (deMachineProcessCount == 1)
		{
			if (!CreateMachine())
			{
				// error - Create failed
				return FALSE;
			}
		}
	} 
	
	if (fdwReason == DLL_PROCESS_DETACH)
	{
		deMachineProcessCount--;
		
		if (deMachineProcessCount == 0)
		{
			if (!DestroyMachine())
			{
				// error - Destroy failed
				return FALSE;
			}
		}
	}
	
	return TRUE; 
}



//=================================================================================
// CreateMachine()
//
// Initialize a machine object from config file settings.  
//=================================================================================

static deBoolean CreateMachine(void)
{
	if (deMachine)
	{
		// Error - Already exists
		return deFALSE;
	}

	// HACK TO MAKE THIS THING WORK
/*
	deRegistry Registry;
	char AppName[120] = "";
	char RegCurrentAppKey[120] = "";
	char DestinyConfigPath[_MAX_PATH + 1] = "";
	int BufferLength = 0;
	char *MachineType = NULL;



	// Get the current running app's name from the registry

	BufferLength = 120;

	if (!Registry.ReadString(RegEngineKey, RegCurrentAppValue, AppName, &BufferLength))
	{
		// error - engine key problem
		return deFALSE;
	}

	if (strlen(AppName) == 0)
	{
		// error - App name not set
		return deFALSE;
	}


	// Get the path from the registry to the current app's Destiny config file

	strcpy(RegCurrentAppKey, RegDestinyKey);
	strcat(RegCurrentAppKey, AppName);

	BufferLength = _MAX_PATH + 1;

	if (!Registry.ReadString(RegCurrentAppKey, RegDestinyConfigPathValue, DestinyConfigPath, &BufferLength))
	{
		// error - Destiny config file path problem
		return deFALSE;
	}

	// Create a config file object with the path

	ConfigFile = new deConfigFile(DestinyConfigPath);

	if (!ConfigFile)
	{
		// error - Could not create a ConfigFile object
		return deFALSE;
	}

	if (!ConfigFile->GetCreationResult())
	{
		// error - Config file load & parse failed
		delete ConfigFile;
		ConfigFile = NULL;
		return deFALSE;
	}


	// Get the machine object type to create

	MachineType = ConfigFile->FindKeyValue(ConfigMachineType);
   
	if (!MachineType)
	{
		// error - Machine type key missing
		delete ConfigFile;
		ConfigFile = NULL;
		return deFALSE;
	}


	// Create the machine object based on type specified in config file

	if (strcmp(MachineType, WindowsMachineType) == 0)
	{
		deMachine = new deMachineWindows;
	}
	else
	{
		// error - Invalid machine type
		delete ConfigFile;
		ConfigFile = NULL;
		return deFALSE;
	}
*/
#ifdef WIN32
	deMachine = new deMachineWindows;
#else
	return deFALSE;
#endif
	// END HACK

	if (!deMachine)
	{
		// error - Machine object create failed
		/*
		delete ConfigFile;
		ConfigFile = NULL;
		*/
		return deFALSE;
	}

	if (!deMachine->GetCreationResult())
	{
		// error - Machine object create failed
		delete deMachine;
		/*
		delete ConfigFile;
		ConfigFile = NULL;
		*/
		deMachine = NULL;
		return deFALSE;
	}

	return deTRUE;
}



//=================================================================================
// DestroyMachine()
//
// Destroy the machine object and any other dynamic objects.  We be done 
// and Windows is going to trash our DLL home real soon now.
//=================================================================================

static deBoolean DestroyMachine(void)
{
	if (deMachine)
		delete deMachine;

	/*
	if (ConfigFile)
		delete ConfigFile;
	*/

	return deTRUE;
}



//=================================================================================
// GetIdeMachineInterface()
//
// This is the only exported function call in the DLL.  It is the only access point 
// for the outside world.  A call to this function will return an interface pointer
// good for an IdeMachine interfaced machine configuration analyzer.  If new interfaces 
// are created, leave this alone and create another export function to feed the new 
// interface objects.  That will maintain backward compatibility. 
//=================================================================================

IdeMachine *GetIdeMachineInterface()
{
   if (deMachine)
   {
      return deMachine;
   }

   //Error - Valid machine object does not exist
   return NULL;
}






