//***************************************************************************************
//
// File supervisor: Softimage Rendering & Pipeline team
//
// (c) Copyright 2001-2005 Avid Technology, Inc. . All rights reserved.
//
//***************************************************************************************

/**************************************************************************************
THIS CODE IS PUBLISHED AS A SAMPLE ONLY AND IS PROVIDED "AS IS".
IN NO EVENT SHALL SOFTIMAGE, AVID TECHNOLOGY, INC. AND/OR THEIR RESPECTIVE
SUPPLIERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS CODE .

COPYRIGHT NOTICE. Copyright © 1999-2005 Avid Technology Inc. . All rights reserved. 

SOFTIMAGE is a registered trademark of Avid Technology Inc. or its subsidiaries 
or divisions. Windows NT is a registered trademark of Microsoft Corp. All other
trademarks contained herein are the property of their respective owners. 
****************************************************************************************/

/*! \file cnv_hierarchytraversal.cpp
/*!
	implementation file for the hierarchy traversal callbacks
*/

#include "stdafx.h"
#include "cnv_hierarchytraversal.h"
#include "cnv_hierarchyelementinfo.h"
#include <xsi_model.h>
#include <xsi_x3dobject.h>
#include <xsi_uitoolkit.h>
#include <Model.h>

/**************************************************************************************
CHierarchyTraverserCallback
**************************************************************************************/
CHierarchyTraverserCallback::CHierarchyTraverserCallback(short in_CryFiletype) :
	m_CryFiletype(in_CryFiletype)
{
};

CHierarchyTraverserCallback::~CHierarchyTraverserCallback() {};

CStatus CHierarchyTraverserCallback::Execute(CdotXSIConverter *in_pContext, CRef in_XSIParent, CSLTemplate *in_pFTKParent, CHierarchyElementInfo *in_pInfo, CRef *io_pXSIModel, CSLTemplate **io_pFTKModel)
{
	CStatus status = CStatus::NotImpl;

	return status;
}

wchar_t *CHierarchyTraverserCallback::GetClassID(){return L"CHierarchyTraversalCallback";}


/**************************************************************************************
CXSIHierarchyTraverser
**************************************************************************************/
CXSIHierarchyTraverser::CXSIHierarchyTraverser() :
	m_eTraverserMode(ALL)
{
	
};

CXSIHierarchyTraverser::~CXSIHierarchyTraverser() 
{
	int loop;

	for(loop = 0; loop < m_CallbackList.GetUsed(); loop++)
	{
		if(m_CallbackList[loop] != NULL)
			delete m_CallbackList[loop];
	}

};

CStatus CXSIHierarchyTraverser::Execute(CdotXSIConverter *in_pContext)
{
	CRef	XSIRoot = in_pContext->scene().GetRoot();

	CSLTemplate	*l_pFTKRoot = (CSLTemplate *)in_pContext->ftkscene()->Root();
	CSLTemplate	*l_pFTKModel = NULL;

	return Traverse(in_pContext, XSIRoot, l_pFTKRoot, in_pContext->GetFirstHierarchyElementInfo(), &XSIRoot, &l_pFTKModel);
}

wchar_t *CXSIHierarchyTraverser::GetClassID(){return L"CXSIHierarchyTraverser";}

CStatus CXSIHierarchyTraverser::Traverse(CdotXSIConverter *in_pContext, CRef in_XSIParent, CSLTemplate *in_pFTKParent, CHierarchyElementInfo* in_pInfo, CRef *io_pXSIModel, CSLTemplate **io_pFTKModel)
{
	CStatus status = CStatus::OK;
	int loop;

	if(in_pInfo)
	{
		*io_pFTKModel = in_pInfo->GetFTKModel();
	}

	X3DObject	l_Object = (X3DObject) *io_pXSIModel;

	if (in_pInfo && (GetTraverserMode() == CXSIHierarchyTraverser::SELECTED))
	{
		if ( in_pInfo->GetSelectionState() == CHierarchyElementInfo::SINGLE || in_pInfo->GetSelectionState() == CHierarchyElementInfo::BRANCH_ROOT )
		{
			CSLTemplate	*l_pFTKRoot = (CSLTemplate *)in_pContext->ftkscene()->Root();

			for(loop = 0; (loop < m_CallbackList.GetUsed()) && (status == CStatus::OK); loop++)
			{
				if (in_pContext->IsCancelPressed())
				{
					logerror ( L"Operation canceled.");
					status = CStatus::False;
					break;
				}

				if (m_CallbackList[loop]->GetCryFiletype() & in_pInfo->GetCryFiletype())
				{
					_XSI_CALL(m_CallbackList[loop]->Execute(in_pContext, in_XSIParent, l_pFTKRoot, in_pInfo, io_pXSIModel, io_pFTKModel), L"Failed to execute traverser callback");
				}
			}
		}
		else if ( in_pInfo->GetSelectionState() == CHierarchyElementInfo::BRANCH_NODE )
		{
			for(loop = 0; (loop < m_CallbackList.GetUsed()) && (status == CStatus::OK); loop++)
			{
				if (in_pContext->IsCancelPressed())
				{
					logerror ( L"Operation canceled.");
					status = CStatus::False;
					break;
				}

				if (m_CallbackList[loop]->GetCryFiletype() & in_pInfo->GetCryFiletype())
				{
					_XSI_CALL(m_CallbackList[loop]->Execute(in_pContext, in_XSIParent, in_pFTKParent, in_pInfo, io_pXSIModel, io_pFTKModel), L"Failed to execute traverser callback");
				}
			}
		}
	}
	else
	{
		for(loop = 0; (loop < m_CallbackList.GetUsed()) && (status == CStatus::OK); loop++)
		{
			if (in_pContext->IsCancelPressed())
			{
				logerror ( L"Operation canceled.");
				status = CStatus::False;
				break;
			}

			// WARNING: Filetype is only taken into account in selection only mode. This is to enable the in_pInfo
			// information gattering, where we set the CryFiletype on it.
			_XSI_CALL(m_CallbackList[loop]->Execute(in_pContext, in_XSIParent, in_pFTKParent, in_pInfo, io_pXSIModel, io_pFTKModel), L"Failed to execute traverser callback");
		}
	}

	bool l_bInfoCreationMode = false;

	CHierarchyElementInfo* l_pInfoNext = in_pInfo;

	CSLModel	*l_pFTKModel = (CSLModel*) (*io_pFTKModel);
	CRefArray	l_Children = l_Object.GetChildren();

	for(loop = 0; (loop < l_Children.GetCount()) && (status == CStatus::OK); loop++)
	{
		if (in_pContext->IsCancelPressed())
		{
			logerror ( L"Operation canceled.");
			status = CStatus::False;
			break;
		}

		CSLTemplate	*l_pCreatedTemplate = NULL; 
		CRef child = l_Children.GetItem(loop);

		// create a hierarchy element info for each element parsed and set it's parent
		if (l_pInfoNext)
		{
			if (l_bInfoCreationMode || !l_pInfoNext->GetNext())
			{
				l_bInfoCreationMode = true;

				l_pInfoNext = in_pContext->AddHierarchyElementInfo();
				l_pInfoNext->SetParent(in_pInfo);
			}
			else
			{
				l_pInfoNext = in_pContext->GetNextHierarchyElementInfo();
			}
		}

		_XSI_CALL(Traverse(in_pContext, *io_pXSIModel, *io_pFTKModel, l_pInfoNext, &child, &l_pCreatedTemplate), L"Failed to execute child traversal");

		// False just means that further processing of callbacks has aborted, but the error is
		// Not critical, we therefore just return OK after
		if(status == CStatus::False && !in_pContext->IsCancelPressed())
			status = CStatus::OK;
	}

	return status;
}

CSIBCArray<CHierarchyTraverserCallback*> &CXSIHierarchyTraverser::callbacks()
{
	return m_CallbackList;
}

/**************************************************************************************
CFTKHierarchyTraverser
**************************************************************************************/
CFTKHierarchyTraverser::CFTKHierarchyTraverser()
{
	
};

CFTKHierarchyTraverser::~CFTKHierarchyTraverser() 
{
	int loop;

	for(loop = 0; loop < m_CallbackList.GetUsed(); loop++)
	{
		if(m_CallbackList[loop] != NULL)
			delete m_CallbackList[loop];
	}

};

CStatus CFTKHierarchyTraverser::Execute(CdotXSIConverter *in_pContext)
{
	CRef		XSIRoot = in_pContext->scene().GetRoot();
	CSLTemplate	*l_pFTKRoot = (CSLTemplate *)in_pContext->ftkscene()->Root();

	if(!in_pContext->args()[1].IsEmpty())
	{
		XSIRoot = in_pContext->args()[1];
	}

	return Traverse(in_pContext, XSIRoot, l_pFTKRoot, in_pContext->GetFirstHierarchyElementInfo(), &XSIRoot, &l_pFTKRoot);
}

wchar_t *CFTKHierarchyTraverser::GetClassID(){return L"CFTKHierarchyTraverser";}

CStatus CFTKHierarchyTraverser::Traverse(CdotXSIConverter *in_pContext, CRef in_XSIParent, CSLTemplate *in_pFTKParent, CHierarchyElementInfo *in_pInfo, CRef *io_pXSIModel, CSLTemplate **io_pFTKModel)
{
	CStatus status = CStatus::OK;
	int loop;

	for(loop = 0; (loop < m_CallbackList.GetUsed()) && (status == CStatus::OK); loop++)
	{
		if (in_pContext->IsCancelPressed())
		{
			logerror ( L"Operation canceled.");
			status = CStatus::False;
			break;
		}

		_XSI_CALL(m_CallbackList[loop]->Execute(in_pContext, in_XSIParent, in_pFTKParent, in_pInfo, io_pXSIModel, io_pFTKModel), L"Failed to execute traverser callback");
	}

	CHierarchyElementInfo *in_pInfoNext = NULL;

	CSLModel *l_pFTKModel = (CSLModel *) *io_pFTKModel;
	for(loop = 0; (loop < l_pFTKModel->GetChildrenCount()) && (status == CStatus::OK); loop++)
	{
		if (in_pContext->IsCancelPressed())
		{
			logerror ( L"Operation canceled.");
			status = CStatus::False;
			break;
		}

		in_pInfoNext = in_pContext->GetNextHierarchyElementInfo();

		CSLTemplate	*l_pChildTemplate = l_pFTKModel->GetChildrenList()[loop]; 
		CRef child;
		_XSI_CALL(Traverse(in_pContext, *io_pXSIModel, *io_pFTKModel, in_pInfoNext, &child, &l_pChildTemplate), L"Failed to execute child traversal");

	}

	return status;
}

CSIBCArray<CHierarchyTraverserCallback*> &CFTKHierarchyTraverser::callbacks()
{
	return m_CallbackList;
}

/**************************************************************************************
CSimpleXSILogging
**************************************************************************************/
CSimpleXSILogging::CSimpleXSILogging(short in_CryFiletype) : CHierarchyTraverserCallback(in_CryFiletype) {};

CSimpleXSILogging::~CSimpleXSILogging() {};

CStatus CSimpleXSILogging::Execute(CdotXSIConverter *in_pContext, CRef in_XSIParent, CSLTemplate *in_pFTKParent, CHierarchyElementInfo *in_pInfo, CRef *io_pXSIModel, CSLTemplate **io_pFTKModel)
{
	CStatus status = CStatus::OK;
	X3DObject model = (X3DObject) *io_pXSIModel;
	X3DObject parent = (X3DObject) in_XSIParent;
	logmessage(L"%s is child of %s", model.GetName().GetWideString(), parent.GetName().GetWideString());

	return status;
}

wchar_t *CSimpleXSILogging::GetClassID(){return L"CSimpleXSILogging";}

/**************************************************************************************
CSimpleFTKLogging
**************************************************************************************/
CSimpleFTKLogging::CSimpleFTKLogging(short in_CryFiletype) : CHierarchyTraverserCallback(in_CryFiletype) {};

CSimpleFTKLogging::~CSimpleFTKLogging() {};

CStatus CSimpleFTKLogging::Execute(CdotXSIConverter *in_pContext, CRef in_XSIParent, CSLTemplate *in_pFTKParent, CHierarchyElementInfo *in_pInfo, CRef *io_pXSIModel, CSLTemplate **io_pFTKModel)
{
	CStatus status = CStatus::OK;
	CSLModel *model = (CSLModel*) *io_pFTKModel;
	CSLModel *parent = (CSLModel*) in_pFTKParent;
	logmessage(L"%s is child of %s", model->Name().GetText(), parent->Name().GetText());

	return status;
}

wchar_t *CSimpleFTKLogging::GetClassID(){return L"CSimpleFTKLogging";}