/***********************************************************************************************************************
*
* Copyright (c) 2010 - 2024 by Tech Soft 3D, Inc.
* The information contained herein is confidential and proprietary to Tech Soft 3D, Inc., and considered a trade secret
* as defined under civil and criminal statutes. Tech Soft 3D shall pursue its civil and criminal remedies in the event
* of unauthorized use or misappropriation of its trade secrets. Use of this information by anyone other than authorized
* employees of Tech Soft 3D, Inc. is granted only under a written non-disclosure agreement, expressly prescribing the
* scope and manner of such use.
*
***********************************************************************************************************************/

/*
* This sandbox can be used to prototype a new sample.
*/

#define INITIALIZE_A3D_API
#include <A3DSDKIncludes.h>

#include "../../common.hpp"
#include <cassert>
#include <iostream>

static MY_CHAR acSrcFileName[_MAX_PATH * 2];
static MY_CHAR acDstFileName[_MAX_PATH * 2];
static MY_CHAR acLogFileName[_MAX_PATH * 2];


//######################################################################################################################
void traverse_tree(A3DTree* const hnd_tree, A3DTreeNode* const hnd_node, size_t depth) {

	///User Code to process node/// 

	//Start node dump
	std::cout << std::string(2 * depth, ' '); // Print indent


	// Display node's entity name
	std::cout << "Name: ";

	A3DUTF8Char* node_name = nullptr;
	if (A3DTreeNodeGetName(hnd_node, &node_name) == A3D_SUCCESS && node_name != nullptr) {
		std::cout << node_name << "; ";
		A3DTreeNodeGetName(A3D_NULL_HANDLE, &node_name);
	}
	else {
		std::cout << "N/A; ";
	}


	// Display node's entity type
	std::cout << "Type: ";

	A3DEntity* pEntity = A3D_NULL_HANDLE;
	A3DTreeNodeGetEntity(hnd_node, &pEntity);
	A3DEEntityType eType = kA3DTypeUnknown;
	if (A3DEntityGetType(pEntity, &eType) == A3D_SUCCESS) {
		const A3DUTF8Char* pTypeMsg = A3DMiscGetEntityTypeMsg(eType);
		std::cout << pTypeMsg << "; ";
	}
	else {
		std::cout << "N/A; ";
	}

	// Display node's color index
	std::cout << "Color: ";

	A3DGraphStyleData node_style = A3D_MAKE_DATA(A3DGraphStyleData);
	if (A3DTreeNodeGetNetStyle(hnd_node, &node_style) == A3D_SUCCESS)
	{
		A3DGraphRgbColorData color = A3D_MAKE_DATA(A3DGraphRgbColorData);
		if (A3DGlobalGetGraphRgbColorData(node_style.m_uiRgbColorIndex, &color) == A3D_SUCCESS) {
			std::cout << "RGB(" << color.m_dRed << ";" << color.m_dGreen << ";" << color.m_dBlue << ")";
			A3DTreeNodeGetNetStyle(A3D_NULL_HANDLE, &node_style);
		}
		else {
			std::cout << "N/A; ";
		}
	}


	//end of node dump
	std::cout << std::endl;


	///End of process node///

	//Recursively call traverse_tree on child nodes
	A3DUns32 n_child_nodes = 0;
	A3DTreeNode** child_nodes = nullptr;

	if (A3DTreeNodeGetChildren(hnd_tree, hnd_node, &n_child_nodes, &child_nodes) == A3D_SUCCESS) {
		for (A3DUns32 n = 0; n < n_child_nodes; ++n) {
			traverse_tree(hnd_tree, child_nodes[n], depth + 1);
		}
		A3DTreeNodeGetChildren(A3D_NULL_HANDLE, A3D_NULL_HANDLE, &n_child_nodes, &child_nodes);
	}
}


//######################################################################################################################
#ifdef _MSC_VER
int wmain(A3DInt32 iArgc, A3DUniChar** ppcArgv)
#else
int main(A3DInt32 iArgc, A3DUTF8Char** ppcArgv)
#endif
{
	//
	// ### COMMAND LINE ARGUMENTS
	//

	if (iArgc > 1) MY_STRCPY(acSrcFileName, ppcArgv[1]);
	else           MY_STRCPY(acSrcFileName, DEFAULT_INPUT_CAD);
	if (iArgc > 2) MY_STRCPY(acDstFileName, ppcArgv[2]);
	else           MY_SPRINTF(acDstFileName, "%s.prc", acSrcFileName);
	if (iArgc > 3) MY_STRCPY(acLogFileName, ppcArgv[3]);
	else           MY_SPRINTF(acLogFileName, "%s_Log.txt", acDstFileName);
	GetLogFile(acLogFileName); // Initialize log file

	//
	// ### INITIALIZE HOOPS EXCHANGE
	//

	A3DSDKHOOPSExchangeLoader sHoopsExchangeLoader(_T(HOOPS_BINARY_DIRECTORY));
	CHECK_RET(sHoopsExchangeLoader.m_eSDKStatus);

	CHECK_RET(A3DDllSetCallbacksMemory(CheckMalloc, CheckFree));
	CHECK_RET(A3DDllSetCallbacksReport(PrintLogMessage, PrintLogWarning, PrintLogError));

	//
	// ### PROCESS SAMPLE CODE
	//

	// specify input file
	A3DImport sImport(acSrcFileName); // see A3DSDKInternalConvert.hxx for import and export detailed parameters

	// Import options
	sImport.m_sLoadData.m_sGeneral.m_bReadSolids = true;
	sImport.m_sLoadData.m_sGeneral.m_bReadWireframes = true;
	sImport.m_sLoadData.m_sGeneral.m_bReadSurfaces = true;
	sImport.m_sLoadData.m_sGeneral.m_bReadPmis = true;
	sImport.m_sLoadData.m_sGeneral.m_bReadAttributes = true;
	sImport.m_sLoadData.m_sGeneral.m_bReadHiddenObjects = true;
	sImport.m_sLoadData.m_sGeneral.m_bReadConstructionAndReferences = false;
	sImport.m_sLoadData.m_sGeneral.m_bReadActiveFilter = true;
	sImport.m_sLoadData.m_sGeneral.m_eReadingMode2D3D = kA3DRead_3D;
	sImport.m_sLoadData.m_sGeneral.m_eReadGeomTessMode = kA3DReadGeomAndTess;
	sImport.m_sLoadData.m_sGeneral.m_eDefaultUnit = kA3DUnitUnknown;
	sImport.m_sLoadData.m_sTessellation.m_eTessellationLevelOfDetail = kA3DTessLODMedium;
	sImport.m_sLoadData.m_sAssembly.m_bUseRootDirectory = true;
	sImport.m_sLoadData.m_sMultiEntries.m_bLoadDefault = true;
	sImport.m_sLoadData.m_sPmi.m_bAlwaysSubstituteFont = false;
	sImport.m_sLoadData.m_sPmi.m_pcSubstitutionFont = (char*)"Myriad CAD";

	// specify output file
	A3DExport sExport(acDstFileName); // see A3DSDKInternalConvert.hxx for import and export detailed parameters

	//JT Export Options
	sExport.m_sExportJTData.m_eWriteGeomTessMode = kA3DWriteGeomAndTess;
	sExport.m_sExportJTData.m_bWritePMI = true;

	//STL Export Options
	sExport.m_sExportStlData.m_eTessellationLevelOfDetail = kA3DTessLODMedium;

	//XML Export Options
	sExport.m_sExportXMLData.m_bExportMetadata = true;
	sExport.m_sExportXMLData.m_bExportTransformations = true;
	sExport.m_sExportXMLData.m_bExportColorMaterial = true;
	sExport.m_sExportXMLData.m_bExportProductInformationByFormat = false;

	//U3D Export Options
	sExport.m_sExportU3DData.m_eU3DVersion = kA3DECMA3;

	//PRC Export Options
	sExport.m_sExportPrcData.m_eCompressBrepType = kA3DCompressionMedium;

	//3MF Export Options
	//sExport.m_sExport3mfData.

	//OBJ Export Options
	//sExport.m_sExportObjData.

	//FBX Export Options
	//sExport.m_sExportFbxData

	//GLTF Export Options
	//sExport.m_sExportGltfData;

	// perform Import
	CHECK_RET(sHoopsExchangeLoader.Import(sImport));

	// process model data   

	//Prepare model tree
	A3DTree* hnd_tree = A3D_NULL_HANDLE;
	A3DStatus status = A3DTreeCompute(sHoopsExchangeLoader.m_psModelFile, &hnd_tree, nullptr);
	assert(status == A3D_SUCCESS);

	//Get root node
	A3DTreeNode* hnd_root_node = A3D_NULL_HANDLE;
	status = A3DTreeGetRootNode(hnd_tree, &hnd_root_node);
	assert(status == A3D_SUCCESS);

	//Process
	traverse_tree(hnd_tree, hnd_root_node, 0);

	//free
	A3DTreeCompute(A3D_NULL_HANDLE, &hnd_tree, nullptr);

	// perform Export 
	CHECK_RET(sHoopsExchangeLoader.Export(sExport));


	//
	// ### TERMINATE HOOPS EXCHANGE
	//

	// Check memory allocations
	return (int)ListLeaks();
}
