/****************************************************************************************

		Modeler.cpp

		Copyright (c)1990 - 1999 MetaCreations. All rights reserved.

		Author:	Jerome Bignon
		Date:	05/18/99

		Revision History

		when		who			what & why
		==========	==========	======================================================
		05/18/99	Jerome		Creation

*****************************************************************************************/

#include "Modeler.h"
#include "ModelerDef.h"
#include "ModelerView.h"

#include "COMUtilities.h"
#include "COM3DUtilities.h"
#include "IShUtilities.h"
#include "I3DEditorHostPartDefs.h"
#include "I3DShModule.h"
#include "IShComponent.h"
#include "ComMessages.h"
#include "IMFResponder.h"
#include "IComponentAnim.h"
#include "COMSafeUtilities.h"

const MCGUID CLSID_Modeler(R_CLSID_Modeler);


Modeler::Modeler()
{
}


MCCOMErr Modeler::QueryInterface(const MCIID& riid, void** ppvObj)
{
	return TBasicModule::QueryInterface(riid, ppvObj);
}

uint32 Modeler::AddRef()
{
	return TBasicModule::AddRef();
}

MCCOMErr Modeler::Initialize(IMCUnknown* inElement)
{
	// Initialize is going to be called twice : once with the Universe, once with the Master Object
	if(!inElement) return MC_E_INVALIDARG;

	TMCCountedPtr<I3DShGroup> universe;
	if(inElement->QueryInterface(IID_I3DShGroup, (void**) &universe) == MC_S_OK)
	{
	// TBasicModule::Initialize(inElement);
		return Initialize1(universe);
	}

	if(!fUniverse) return MC_E_INVALIDARG;

	TMCCountedPtr<I3DShPrimitive> primitive;
	if(inElement->QueryInterface(IID_I3DShPrimitive, (void**)&primitive) == MC_S_OK)
	{
		return Initialize2(primitive);
	}

	return MC_E_INVALIDARG;
}

MCCOMErr Modeler::Initialize1(I3DShGroup* universe)
{
	// Initialization Call #1 : the Universe is passed

	if(!universe) return MC_E_INVALIDARG;
	fUniverse = universe;
	
	return MC_S_OK;
}

MCCOMErr Modeler::Initialize2(I3DShPrimitive* primitive)
{
	// Initialization Call #2 : the Master Object (primitive) is passed
	//-- Get target data
	fShPrimitive = primitive;
	ThrowIfNil(fShPrimitive);

	TMCCountedPtr<I3DShExternalPrimitive> externalPrimitive;
	fShPrimitive->QueryInterface(IID_I3DShExternalPrimitive, (void**) &externalPrimitive);
	ThrowIfNil(externalPrimitive);

	TMCCountedPtr<IShComponent> component;
	externalPrimitive->GetPrimitiveComponent(&component);
	ThrowIfNil(component);

	TMCCountedPtr<I3DShPrimitiveComponent> primitiveComponent;
	component->QueryInterface(IID_I3DShPrimitiveComponent, (void**) &primitiveComponent);
	ThrowIfNil(primitiveComponent);

	TMCCountedPtr<IMCUnknown> extPrimitive;
	primitiveComponent->GetExternalPrimitive(&extPrimitive);
	ThrowIfNil(extPrimitive);

	extPrimitive->QueryInterface(IID_I3DExGeometricPrimitive, (void**)&fExPrimitive);
	ThrowIfNil(fExPrimitive);

	extPrimitive->QueryInterface(IID_ITreePrim, (void**) &fCOMTreePrim);
	ThrowIfNil(fCOMTreePrim);

	//-- Load windows and set up UI elements
	CreateWindows();

	//-- Register ourselves as listeners to some channels
	fScene->GetTimeChangeChannel(&fTimeChangeChannel);
	ThrowIfNil(fTimeChangeChannel);
	fTimeChangeChannel->RegisterListener(this);

	return MC_S_OK;
}

MCCOMErr Modeler::Destroy()	
{
	DestroyWindows();

	//-- Clear everything
	fHierarchyModule = NULL;
	fUniverse = NULL;
	fWindow = NULL;
	fShPrimitive = NULL;

	//-- Deregister ourselves as listeners
	if (fTimeChangeChannel)	fTimeChangeChannel->UnregisterListener(this);
	fTimeChangeChannel = NULL;

	return TBasicModule::Destroy();
}

MCCOMErr Modeler::Hydrate()
{
	TMCCountedPtr<IMFWindow> win;
	fWindow->QueryInterface(IID_IMFWindow, (void **)&win); ThrowIfNil(win);
	win->Show(true, false);
	gMenuUtilities->SetCurrentGlobalTool(kMoveToolID, true);
	
	//-- Hydrate other Modules
	if (fHierarchyModule)
		fHierarchyModule->Hydrate();
	return TBasicModule::Hydrate();
}

MCCOMErr Modeler::Dehydrate()
{
	//-- Dehydrate other Modules
	if (fHierarchyModule)
		fHierarchyModule->Dehydrate();

	//-- Hide window
	if (fWindow)
	{
		TMCCountedPtr<IMFWindow> win;
		fWindow->QueryInterface(IID_IMFWindow, (void **)&win); ThrowIfNil(win);
		win->Show(false, false);
	}

	return TBasicModule::Dehydrate();
}

MCCOMErr Modeler::Activate()
{
	//-- Select window
	TMCCountedPtr<IMFWindow> win;
	fWindow->QueryInterface(IID_IMFWindow, (void**) &win);	ThrowIfNil(win);
	win->SelectWindow();

	//-- Activate other Modules
	if (fHierarchyModule)
		fHierarchyModule->Activate();
	return MC_S_OK;
}

MCCOMErr Modeler::Deactivate()
{
	//-- Deactivate other Modules
	if (fHierarchyModule)
		fHierarchyModule->Deactivate();
	//--
	return MC_S_OK;
}

void Modeler::GetActionResponder(IMFResponder** responder)
{
	fDoc->QueryInterface(IID_IMFResponder, (void**) responder);
}

/*
void Modeler::DataChanged(IChangeChannel*		channel, 
							 IDType 			changeKind, 
							 IMCUnknown* 		changedData)
{
	if (channel == fTimeChangeChannel)
	{//-- Time changed
		AttachHostToPrimitive();
	}

	TBasicModule::DataChanged(channel, changeKind, changedData);
}
*/
void  Modeler::CreateWindows()
{
	QueryInterface(IID_I3DShModule, (void**) &fModule);
	ThrowIfNil(fModule);

	fDoc = fModule->GetDocumentNoAddRef();
	ThrowIfNil(fDoc);

	fDoc->QueryInterface(IID_ISceneDocument, (void**) &fSceneDoc);
	ThrowIfNil(fSceneDoc);

	fSceneDoc->GetScene(&fScene);
	ThrowIfNil(fScene);

	void* oldResources = NULL;
	gResourceUtilities->SetupComponentResources('modu', kModelerID, &oldResources);
	
	fModule->CreateWindowByResource(&fWindow, kModelerView, true);
 	ThrowIfNil(fWindow);
	
	fWindow->FindChildPartByID(&fMainPart, 'MODv');

	fMainPart->QueryInterface(IID_IModelerView, (void**) &fModelerPart);
	ThrowIfNil(fModelerPart);

	fModelerPart->SetModeler(this);

	gResourceUtilities->RestoreComponentResources(oldResources);
}

void Modeler::DestroyWindows()
{
	fModule = NULL;
	fDoc = NULL;
	fSceneDoc = NULL;
	fScene = NULL;
	fWindow = NULL;
	fMainPart = NULL;
}

MCCOMErr Modeler::AboutToCloseMainWindow()
{
	DestroyWindows();
	return MC_S_OK;
}
