/*
	Copyright (c) 2024 PTC Inc. and/or Its Subsidiary Companies. All Rights Reserved.
*/


#include <ProToolkit.h>
#include <ProWorkspace.h>
#include <ProWTUtils.h>
#include <ProBrowser.h>
#include <ProUtil.h>
#include <ProMenuBar.h>
#include <ProMode.h>
#include <ProDrawing.h>
#include <ProSolid.h>

#include <PTWCServer.h>

typedef struct
{
	wchar_t* server;
	wchar_t* ws_name;
	ProPath ws_path;
} PTWCAsmVisitData;

/*====================================================================*\
  FUNCTION: PTWCAddPartToPviewAsSecondary
  PURPOSE:  Visit action for each part in the assembly.  Checkout the 
			part, export it to ProductView and add the results as 
			secondary content
\*====================================================================*/
static ProError PTWCAddPartToPviewAsSecondary (ProAsmcomppath* path, ProSolid solid,
											   ProError filter_status, ProAppData data)
{
	PTWCAsmVisitData* visit_data = (PTWCAsmVisitData*)data;
	ProMdlType type;
	ProMdlName modelname;
	ProMdlFileName objectname;
	ProPath directory, filepath;
	ProBoolean checkedout, modified;
	wchar_t* model_url;
	ProServerCheckoutConflicts conflicts;
	ProSolid generic = NULL;
	ProServerCheckoutOptions co_options;

/*--------------------------------------------------------------------*\
	Ensure that the model is a part, and export it to ProductView format
\*--------------------------------------------------------------------*/
	status = ProMdlTypeGet (solid, &type);
	PT_TEST_LOG_SUCC ("ProMdlTypeGet()");

	if (status != PRO_TK_NO_ERROR || type != PRO_MDL_PART)
		return PRO_TK_NO_ERROR;

	status = ProProductviewExport (solid, NULL, NULL);
	PT_TEST_LOG_SUCC ("ProProductviewExport()");

/*--------------------------------------------------------------------*\
	Derive the workspace path for the model
\*--------------------------------------------------------------------*/
	status = ProMdlMdlnameGet (solid, modelname);
	PT_TEST_LOG_SUCC ("ProMdlMdlnameGet()");

	PTWCUtilWstringToLower (modelname);

	ProWstringCopy (modelname, objectname, PRO_VALUE_UNUSED);
	ProWstringConcatenate (L".prt", objectname, PRO_VALUE_UNUSED);

/*--------------------------------------------------------------------*\
	If the object is not checked out, check it out.  If the object is
	an instance, checkout its top level generic with instances instead.
\*--------------------------------------------------------------------*/
	status = ProServerObjectStatusGet (visit_data->server, visit_data->ws_name,
										objectname, &checkedout, &modified);
	PT_TEST_LOG_SUCC ("ProServerObjectStatusGet()");

	if (status != PRO_TK_NO_ERROR || !checkedout)
	{
		status = ProServercheckoutoptsAlloc (&co_options);
		PT_TEST_LOG_SUCC ("ProServercheckoutoptsAlloc()");

		status = ProServercheckoutoptsIncludeinstancesSet (co_options, 
															PRO_SERVER_INCLUDE_ALL,
															NULL);
		PT_TEST_LOG_SUCC ("ProServercheckoutoptsIncludeinstancesSet()");

		status = ProFaminstanceGenericGet (solid, PRO_B_FALSE, 
										   (ProMdl*)&generic);
		PT_TEST_LOG_SUCC ("ProFaminstanceGenericGet()");

		status = ProServerObjectsCheckout (status == PRO_TK_NO_ERROR ? generic : solid, 
										NULL, PRO_B_TRUE, 
										co_options, &model_url, &conflicts);
		PT_TEST_LOG_SUCC ("ProServerObjectsCheckout()");

		ProWstringFree (model_url);
		ProServercheckoutoptsFree (co_options);
	}

	if (status == PRO_TK_CHECKOUT_CONFLICT)
	{
		PTWCUtilSetInteractive (PRO_B_FALSE);
		PTWCUtilConflictReport (conflicts);
		ProServerconflictsFree (conflicts);
		PTWCUtilSetInteractive (PRO_B_TRUE);
	}
	else
	{
/*--------------------------------------------------------------------*\
	Copy the ProductView .ol file as secondary content
\*--------------------------------------------------------------------*/
		status = ProDirectoryCurrentGet (directory);
		PT_TEST_LOG_SUCC ("ProDirectoryCurrentGet()");

		ProWstringCopy (directory, filepath, PRO_VALUE_UNUSED);
		ProWstringConcatenate (modelname, filepath, PRO_VALUE_UNUSED);
		ProWstringConcatenate (L".ol", filepath, PRO_VALUE_UNUSED);

		status = ProFileCopyToWS (filepath, visit_data->ws_path, objectname);
		PT_TEST_LOG_SUCC ("ProFileCopyToWS()");

/*--------------------------------------------------------------------*\
	Copy the ProductView .ed file as secondary content
\*--------------------------------------------------------------------*/
		ProWstringCopy (directory, filepath, PRO_VALUE_UNUSED);
		ProWstringConcatenate (modelname, filepath, PRO_VALUE_UNUSED);
		ProWstringConcatenate (L".ed", filepath, PRO_VALUE_UNUSED);

		status = ProFileCopyToWS (filepath, visit_data->ws_path, objectname);
		PT_TEST_LOG_SUCC ("ProFileCopyToWS()");
	}

	return (PRO_TK_NO_ERROR);
}

/*====================================================================*\
  FUNCTION: PTWCPartsToProductView
  PURPOSE:  Export OL/ED files for each part, add as secondary content,
            and checkin modified models.
\*====================================================================*/
int PTWCPartsToProductView ()
{
	ProMdl model;
	ProMdlType type;
	PTWCAsmVisitData visit_data;

/*--------------------------------------------------------------------*\
	Get the target models to be processed: the active part or assembly,
	or the current solid in the active drawing
\*--------------------------------------------------------------------*/
	status = ProMdlCurrentGet (&model);
	PT_TEST_LOG_SUCC ("ProMdlCurrentGet()");

	status = ProMdlTypeGet (model, &type);
	PT_TEST_LOG_SUCC ("ProMdlTypeGet()");

	if (type == PRO_MDL_DRAWING)
	{
		status = ProDrawingCurrentsolidGet ((ProDrawing)model, 
											(ProSolid*)&model);
		PT_TEST_LOG_SUCC ("ProDrawingCurrsolidGet()");

		status = ProMdlTypeGet (model, &type);
		PT_TEST_LOG_SUCC ("ProMdlTypeGet()");
	}

/*--------------------------------------------------------------------*\
	Save some details about the active server to use for each visited
	model.
\*--------------------------------------------------------------------*/
	status = ProServerActiveGet (&visit_data.server);
	PT_TEST_LOG_SUCC ("ProServerActiveGet()");

	status = ProServerWorkspaceGet (visit_data.server, &visit_data.ws_name);
	PT_TEST_LOG_SUCC ("ProServerWorkspaceGet()");
	
	PTWCUtilBuildWSPath (visit_data.server, visit_data.ws_name, visit_data.ws_path);

/*--------------------------------------------------------------------*\
	Process the single part, or all displayed parts in the assembly
\*--------------------------------------------------------------------*/
	if (type == PRO_MDL_PART)
	{
		PTWCAddPartToPviewAsSecondary (NULL, model, PRO_TK_NO_ERROR, 
										(ProAppData)&visit_data);
	}
	else
	{
		status = ProSolidDispCompVisit (model, PTWCAddPartToPviewAsSecondary,
										NULL, (ProAppData)&visit_data);
		PT_TEST_LOG_SUCC ("ProSolidDispCompVisit()");
	}

/*--------------------------------------------------------------------*\
	Check in all changes
\*--------------------------------------------------------------------*/
	PTWCUtilCheckinWSToFolder (visit_data.ws_name, NULL);

	ProWstringFree (visit_data.server);
	ProWstringFree (visit_data.ws_name);

	return 0;
}

/*====================================================================*\
  FUNCTION: PTWCAccessPartToPView
  PURPOSE:  Access function for the "part to ProductView" command
\*====================================================================*/
uiCmdAccessState PTWCAccessPartToPView (uiCmdAccessMode m)
{
	ProMode mode;
	wchar_t* server;
	wchar_t* server_class;
	int result;

	status = ProModeCurrentGet (&mode);
	
	if (mode != PRO_MODE_PART && mode != PRO_MODE_ASSEMBLY && mode != PRO_MODE_DRAWING)
		return ACCESS_REMOVE;

/*--------------------------------------------------------------------*\
	Ensure that there is an active Windchill server
\*--------------------------------------------------------------------*/
	return (PTWCUtilAccessIfWCServer ());
}