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


#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
/*---------------------- Pro/Toolkit Includes ------------------------*/

#include <ProToolkit.h>
#include <ProMenu.h>
#include <ProMdl.h>
#include <ProIntf3Dexport.h>
#include <ProShrinkwrap.h>
#include <ProFaminstance.h>
#include <ProSolid.h>
#include <ProToolkitDll.h>
#include <ProSimprep.h>
#include <ProDrawing.h>
#include <ProUtil.h>
#include <ProModelitem.h>
#include <ProWstring.h>
#include <ProTKRunTime.h>
#include <ProMessage.h>
#include <UtilString.h>
/*---------------------- Application Includes ------------------------*/
#include <TestError.h>

#define MSGFIL L##"msg_uginterface.txt"

static ProError UserDBSObjectTypeGet(ProArgument* input_arguments, ProName label, int* object_type);

static ProError UserDBSObjectNameGet (ProArgument* input_arguments, ProName label, ProName name);
/*====================================================================*\
FUNCTION: UserIGESGeomflagsExport()
PURPOSE:  Export the current model to IGES 
\*====================================================================*/
int UserIGESGeomflagsExport()
{
  	ProError status;
	ProMdl model;
	ProMdlType type;
	ProPath output_file;
	wchar_t* input;

	status = ProMdlCurrentGet (&model);
	if (status != PRO_TK_NO_ERROR)
		return PRO_TK_GENERAL_ERROR;

	status = ProMdlTypeGet (model, &type);

	if (type != PRO_MDL_PART && type != PRO_MDL_ASSEMBLY)
		return PRO_TK_GENERAL_ERROR;

/*--------------------------------------------------------------------*\
	Prompt the user for the directory in which the export file will go.
\*--------------------------------------------------------------------*/
	ProMessageDisplay (MSGFIL, 
					"USER Select directory location for output file");
	status = ProDirectoryChoose (NULL, NULL, NULL, NULL, output_file);

/*--------------------------------------------------------------------*\
	Prompt the user for the name of the export file
\*--------------------------------------------------------------------*/
	status = UserPromptUI ("Export IGES file", "Enter IGES file name",
					PRO_NAME_SIZE - 1, &input);
	if (status != PRO_TK_NO_ERROR)
		return status;
	else
	{
#if OS_API == WINDOWS
		ProUtilWstrcat (output_file, L"\\");
#else
		ProUtilWstrcat (output_file, "/");
#endif
		ProUtilWstrcat (output_file, input);
		ProUtilWstrcat (output_file, L".igs");
		ProWstringFree (input);
	}

	UserSolidIGESExportWithFlags (model, NULL, output_file);	

	return(PRO_TK_NO_ERROR);	
}

/*====================================================================*\
FUNCTION: UserSolidIGESExportWithFlags()
PURPOSE:  Exports a model to IGES
\*====================================================================*/

int UserSolidIGESExportWithFlags(ProSolid solid, 
								 ProSelection reference_csys,
								ProPath output_file)
{
	ProError status;
	ProIntf3DExportType output_format = PRO_INTF_EXPORT_IGES;
	ProOutputAssemblyConfiguration asm_config = 
									PRO_OUTPUT_ASSEMBLY_MULTI_FILES;
	ProOutputBrepRepresentation brep_flags;
	ProBoolean is_supported;

/*--------------------------------------------------------------------*\
	Verify that this is a permitted assembly configuration option	
\*--------------------------------------------------------------------*/
	status = ProOutputAssemblyConfigurationIsSupported (output_format, 
													asm_config,
													&is_supported);
	if (status != PRO_TK_NO_ERROR || !is_supported)
	{
		ProMessageDisplay (MSGFIL, 
					"USER Assembly configuration is not supported!");
		return PRO_TK_BAD_INPUTS;
	}


/*--------------------------------------------------------------------*\
	Preallocate geometry flags for export
\*--------------------------------------------------------------------*/
	status = ProOutputBrepRepresentationAlloc (&brep_flags);

	status = ProOutputBrepRepresentationFlagsSet (brep_flags,
											PRO_B_FALSE,
											PRO_B_TRUE,
											PRO_B_FALSE,
											PRO_B_FALSE);

/*--------------------------------------------------------------------*\
	Verify that these flags are supported for this export type		
\*--------------------------------------------------------------------*/
	status = ProOutputBrepRepresentationIsSupported (output_format, 
													brep_flags,
													&is_supported);
	if (status != PRO_TK_NO_ERROR || !is_supported)
	{
		ProMessageDisplay (MSGFIL, 
					"USER B-rep flag combination is not supported!");
		ProOutputBrepRepresentationFree (brep_flags);

		return PRO_TK_BAD_INPUTS;
	}

	
/*--------------------------------------------------------------------*\
	Export IGES file(s)
\*--------------------------------------------------------------------*/
	ProIntf3DFileWriteWithDefaultProfile(solid, output_format, output_file);

/*--------------------------------------------------------------------*\
	Free input argument memory
\*--------------------------------------------------------------------*/
	ProOutputBrepRepresentationFree (brep_flags);

	return PRO_TK_NO_ERROR;
}

/*====================================================================*\
FUNCTION: UserShrinkwrapExport()
PURPOSE:  Export the current model to a shrinkwrap (VRML) 
\*====================================================================*/
int UserShrinkwrapExport()
{
  	ProError status;
	ProMdl model;
	ProMdlType type;
	ProMdlName output_file;
	wchar_t* input;
	
	status = ProMdlCurrentGet (&model);
	if (status != PRO_TK_NO_ERROR)
		return PRO_TK_GENERAL_ERROR;

	status = ProMdlTypeGet (model, &type);

	if (type != PRO_MDL_PART && type != PRO_MDL_ASSEMBLY)
		return PRO_TK_GENERAL_ERROR;

/*--------------------------------------------------------------------*\
	Prompt user for the name of the shrinkwrap file name
\*--------------------------------------------------------------------*/
	status = UserPromptUI ("Create shrinkwrap model", 
							"Enter shrinkwrap VRML file name",
							PRO_MDLNAME_SIZE - 1, &input);
	if (status != PRO_TK_NO_ERROR)
		return status;
	else
	{
		ProUtilWstrcpy (output_file, input);
		ProWstringFree (input);
	}

	UserShrinkwrapExportToVRML (model, output_file);
		

	return(PRO_TK_NO_ERROR);	
}

/*====================================================================*\
FUNCTION: UserShrinkwrapExportToVRML()
PURPOSE:  Exports a model to VRML shrinkwrap
\*====================================================================*/

int UserShrinkwrapExportToVRML(ProSolid solid, 
								ProMdlName output_file_name)
{
	ProError status;
	ProShrinkwrapOptions options;

/*--------------------------------------------------------------------*\
	Preallocate needed input arguments
\*--------------------------------------------------------------------*/
	status = ProShrinkwrapoptionsAlloc (PRO_SWCREATE_FACETED_SOLID, 
										&options);

	status = ProShrinkwrapoptionsAutoholefillingSet (options, 
													PRO_B_FALSE);

	status = ProShrinkwrapoptionsFacetedformatSet (options, 
													PRO_SWFACETED_VRML);

/*--------------------------------------------------------------------*\
	Export shrinkwrap file
\*--------------------------------------------------------------------*/
	status = ProSolidShrinkwrapMdlnameCreate (solid, NULL, output_file_name, 
										options);

/*--------------------------------------------------------------------*\
	Free input argument memory
\*--------------------------------------------------------------------*/
	ProShrinkwrapoptionsFree (options);

	return PRO_TK_NO_ERROR;

}

/*====================================================================*\
FUNCTION: UserNewShrinkwrapCreate()
PURPOSE:  Creates a new shrinkwrap merged solid from the current model 
\*====================================================================*/
int UserNewShrinkwrapCreate()
{
  	ProError status;
	ProMdl model;
	ProMdlType type;
	ProMdlName  new_model_name;
	wchar_t* input;

	status = ProMdlCurrentGet (&model);
	if (status != PRO_TK_NO_ERROR)
		return PRO_TK_GENERAL_ERROR;

	status = ProMdlTypeGet (model, &type);

	if (type != PRO_MDL_PART && type != PRO_MDL_ASSEMBLY)
		return PRO_TK_GENERAL_ERROR;

/*--------------------------------------------------------------------*\
	Prompt the user for the name of the new shrinkwrap model
\*--------------------------------------------------------------------*/
	status = UserPromptUI ("Create shrinkwrap model", 
							"Enter new shrinkwrap model name",
							PRO_MDLNAME_SIZE - 1, &input);
	if (status != PRO_TK_NO_ERROR)
		return status;
	else
	{
		ProUtilWstrcpy (new_model_name, input);
		ProWstringFree (input);
	}

	UserShrinkwrapCreateInNewModel (model, new_model_name);
		
	return(PRO_TK_NO_ERROR);	
}

/*====================================================================*\
FUNCTION: UserShrinkwrapCreateInNewModel()
PURPOSE:  Creates a new Shrinkwrap part model as a merged solid.
\*====================================================================*/

int UserShrinkwrapCreateInNewModel(ProSolid solid, 
									ProMdlName new_model_name)
{
	ProError status;
	ProShrinkwrapOptions options;
	ProSolid new_model;

/*--------------------------------------------------------------------*\
	Preallocate needed input arguments
\*--------------------------------------------------------------------*/
	status = ProShrinkwrapoptionsAlloc (PRO_SWCREATE_MERGED_SOLID, 
										&options);

	status = ProShrinkwrapoptionsAssignmasspropsSet (options, 
													PRO_B_TRUE);

/*--------------------------------------------------------------------*\
	Export shrinkwrap file
\*--------------------------------------------------------------------*/
	status = ProSolidMdlnameCreate (new_model_name, PRO_MDLFILE_PART, &new_model);

	status = ProSolidShrinkwrapMdlnameCreate (solid, new_model, NULL, options);

/*--------------------------------------------------------------------*\
	Free input argument memory
\*--------------------------------------------------------------------*/
	ProShrinkwrapoptionsFree (options);

	return PRO_TK_NO_ERROR;

}

/*====================================================================*\
FUNCTION: UserInstanceCreationTask()
PURPOSE:  Loads a given instance of the current Distributed Pro/BATCH generic
                 model.  This instance will be considered the current model fo any subsequent 
		 tasks in the TTD.
\*====================================================================*/

PRO_TK_DLL_EXPORT ProError UserInstanceCreationTask(ProArgument* input_args, ProArgument** output_args)
{
	ProMdlName object_name;
	ProFileName input_file;
	ProMdl model_handle;
	int mdl_type;
	ProFamtable family_table;
	ProFamilyName part_name;
	ProName f_name;
        ProFaminstance f_inst;
	ProMdl inst_model;
	ProArgument *op_args;
	ProMdlName model_name;
	ProMdlType model_type = PRO_MDL_UNUSED;
	char p [PRO_PATH_SIZE ];
	ProName type;
	char name [PRO_PATH_SIZE];
	ProError status;

/*--------------------------------------------------------------------*\
	Get the object name and its type loaded through Dbatch.
\*--------------------------------------------------------------------*/
	
	status = UserDBSObjectNameGet (input_args, L"DBS_CURRENT_OBJECT_NAME",object_name); 
	
	status = UserDBSObjectTypeGet (input_args,L"DBS_CURRENT_OBJECT_TYPE",&mdl_type);
	
	
	if (mdl_type == PRO_MDL_UNUSED)
  	{
	  	status = PRO_TK_BAD_INPUTS;
		return status;
  	}
	
/*--------------------------------------------------------------------*\
	Initialise the model handle.
\*--------------------------------------------------------------------*/
        
	status = ProMdlnameInit(object_name, (ProMdlfileType)mdl_type, &model_handle);
  	
/*--------------------------------------------------------------------*\
	Initiaise the family table
\*--------------------------------------------------------------------*/
	
	status = ProFamtableInit (model_handle, &family_table);
	
/*--------------------------------------------------------------------*\
	Get the USER_DATA from TTD passed by user.
\*--------------------------------------------------------------------*/
	
	status = UserDBSObjectNameGet (input_args, L"INST_NAME",f_name); 
	
/*--------------------------------------------------------------------*\
	Initialise the family instance handle
\*--------------------------------------------------------------------*/ 
	 
	 status = ProFaminstanceInit(f_name,&family_table,&f_inst);
	
/*--------------------------------------------------------------------*\
	Create the instance model of specified instance handle
\*--------------------------------------------------------------------*/ 
	 
	status = ProFaminstanceRetrieve (&f_inst, &inst_model);
	
/*--------------------------------------------------------------------*\
	Put the output model (its name and type) in output arguments
\*--------------------------------------------------------------------*/ 
	
	status = ProArrayAlloc ( 2, sizeof (ProArgument), 1, (ProArray*) &op_args);
  
	status = ProMdlMdlnameGet(inst_model,model_name);
	
	/* Instance model object name*/
  	
	ProStringToWstring (op_args[0].label, "DBS_CURRENT_OBJECT_NAME");
  	op_args[0].value.type = PRO_VALUE_TYPE_WSTRING;
  	ProValuedataWstringSet (&op_args[0].value, model_name);
	
	status = ProMdlTypeGet(inst_model, &model_type);

/*--------------------------------------------------------------------*\
	Convert instance model type to string and then to wide string. (Output
	arguments only take wstring type of data)
\*--------------------------------------------------------------------*/ 
	 
	 ProTKSprintf(p,"%d",model_type);
	 
	 ProStringToWstring(type,p);

  	 ProStringToWstring (op_args[1].label, "DBS_CURRENT_OBJECT_TYPE");
  	 op_args[1].value.type = PRO_VALUE_TYPE_WSTRING;
  	 ProValuedataWstringSet (&op_args[1].value, type);
	
	*output_args = op_args;
  	status = PRO_TK_NO_ERROR;
	
	return status;
}

/*====================================================================*\
FUNCTION: UserSimprepActivateTask()
PURPOSE:  Activates a simplified representation of the current Distributed
          	 Pro/BATCH model.  This simplified rep will be considered the current model 
          	 for any subsequent tasks in the TTD.
\*====================================================================*/

PRO_TK_DLL_EXPORT ProError UserSimprepActivateTask(ProArgument* input_args, ProArgument**output_args)
{
	ProMdlName object_name;
	ProFileName input_file;
	ProMdl model_handle;
	ProMdlType mdl_type = PRO_MDL_UNUSED;
	ProSimprep simp_rep;
	ProFileName file_name, file;
	ProName rep_name;
	ProError status;

/*--------------------------------------------------------------------*\
	Get the object name and its type loaded through Dbatch.
\*--------------------------------------------------------------------*/
	
	status = UserDBSObjectNameGet (input_args, L"DBS_CURRENT_OBJECT_NAME",object_name); 
	
	status = UserDBSObjectTypeGet (input_args,L"DBS_CURRENT_OBJECT_TYPE",(int *)&mdl_type);	
	
	if (mdl_type == PRO_MDL_UNUSED)
  	{
	  	status = PRO_TK_BAD_INPUTS;
		return status;
  	}
	
/*--------------------------------------------------------------------*\
	Initialise the model handle.
\*--------------------------------------------------------------------*/
	
	status = ProMdlnameInit(object_name, (ProMdlfileType)mdl_type, &model_handle);
	
/*--------------------------------------------------------------------*\
	Get the USER_DATA from TTD passed by user.
\*--------------------------------------------------------------------*/	
	
	status = UserDBSObjectNameGet (input_args, L"SIMP_REP",rep_name); 
	
/*--------------------------------------------------------------------*\
	 Initialise the simplified representation.
\*--------------------------------------------------------------------*/
	
	status = ProSimprepInit (rep_name,-1,(ProSolid)model_handle, &simp_rep);
	 
/*--------------------------------------------------------------------*\
	 Activate the specified simplified representation
\*--------------------------------------------------------------------*/
	status = ProSimprepActivate((ProSolid)model_handle,&simp_rep);
	
	status = ProMdlEraseNotDisplayed();
	
	return status;
} 

/*====================================================================*\
FUNCTION: UserSheetExportTask()
PURPOSE:  Set the current sheet for the current Distributed Pro/BATCH
		 drawing. This current sheet will be used in any subsequent export tasks
          	 in the TTD if those tasks process only the current sheet.
\*====================================================================*/

PRO_TK_DLL_EXPORT ProError UserSheetExportTask(ProArgument* input_args, ProArgument**output_args)
{
	ProMdlName object_name, sheet_name;
	ProFileName input_file;
	ProMdl model_handle;
	ProMdlType mdl_type = PRO_MDL_UNUSED;
	int number;
	char  sheet_no[PRO_NAME_SIZE]; 
  	ProError status;
	
/*--------------------------------------------------------------------*\
	Get the object name and its type loaded through Dbatch.
\*--------------------------------------------------------------------*/
	
	status = UserDBSObjectNameGet (input_args, L"DBS_CURRENT_OBJECT_NAME",object_name); 
	
	status = UserDBSObjectTypeGet (input_args,L"DBS_CURRENT_OBJECT_TYPE",(int *)&mdl_type);
	
	if (mdl_type == PRO_MDL_UNUSED)
  	{
	  	status = PRO_TK_BAD_INPUTS;
		return status;
  	}
	
/*--------------------------------------------------------------------*\
	Initialise the model handle.
\*--------------------------------------------------------------------*/
	
        status = ProMdlnameInit(object_name, (ProMdlfileType)mdl_type, &model_handle);
	 
/*--------------------------------------------------------------------*\
	Get the USER_DATA from TTD passed by user.
\*--------------------------------------------------------------------*/	
	
	status = UserDBSObjectNameGet (input_args, L"SHEET_NO",sheet_name); 
	
	ProWstringToString (sheet_no,sheet_name);

	number = atoi(sheet_no);
	 
/*--------------------------------------------------------------------*\
	  Set the current sheet number of specified drawing.
\*--------------------------------------------------------------------*/
	 
	 status = ProDrawingCurrentSheetSet((ProDrawing)model_handle, number);
	
	 return status;
}

/*====================================================================*\
FUNCTION: UserRegenerateTask()
PURPOSE:  Force a full regeneration of the current Distributed Pro/BATCH
          	 solid model.  If the regeneration succeeds, the model is saved.
         	 If the regeneration fails, this information is stored to the task log file.
\*====================================================================*/

PRO_TK_DLL_EXPORT ProError UserRegenerateTask(ProArgument* input_args, ProArgument** output_args)
{
	ProMdlName object_name;
	ProFileName input_file;
	ProMdl model_handle;
	ProMdlType mdl_type = PRO_MDL_UNUSED;
	ProError status;
		
/*--------------------------------------------------------------------*\
	Get the object name and its type loaded through Dbatch.
\*--------------------------------------------------------------------*/

	status = UserDBSObjectNameGet (input_args, L"DBS_CURRENT_OBJECT_NAME",object_name); 
	
	status = UserDBSObjectTypeGet (input_args,L"DBS_CURRENT_OBJECT_TYPE",(int *)&mdl_type);
	
	if (mdl_type == PRO_MDL_UNUSED)
  	{
	  	status = PRO_TK_BAD_INPUTS;
		return status;
  	}
	
/*--------------------------------------------------------------------*\
	Initialise the model handle.
\*--------------------------------------------------------------------*/
	
        status = ProMdlnameInit(object_name, (ProMdlfileType)mdl_type, &model_handle);
		
/*--------------------------------------------------------------------*\
	Regenerate the solid.
\*--------------------------------------------------------------------*/
	
	status = ProSolidRegenerate((ProSolid)model_handle,PRO_REGEN_FORCE_REGEN);
	
	if (status == PRO_TK_NO_ERROR)
	{
		status = ProMdlSave(model_handle);
	}

	return PRO_TK_NO_ERROR;
}

/*====================================================================*\
FUNCTION: UserDBSObjectNameGet()
PURPOSE:  Get the object name loaded through Dbatch.
\*====================================================================*/

ProError UserDBSObjectNameGet (ProArgument* input_arguments, ProName label, ProMdlName name)
{
	
	ProValueData data;
	int length;
	ProError status;
	
	/*--------------------------------------------------------------------*\
	Get the value of argument
	\*--------------------------------------------------------------------*/

	status = ProArgumentByLabelGet(input_arguments, label, &data);

	if (status != PRO_TK_NO_ERROR)
    	return status;
	
	/*--------------------------------------------------------------------*\
	Data will always be of wstring type
	\*--------------------------------------------------------------------*/

	if (data.type != PRO_VALUE_TYPE_WSTRING)
	{
    		status = PRO_TK_INVALID_TYPE;
		return status;
	}
	ProWstringLengthGet (data.v.w, &length);
	
	if (length > PRO_NAME_SIZE -1)
	{
		status = PRO_TK_LINE_TOO_LONG;
		return status;
	}
	
	/*--------------------------------------------------------------------*\
	Copy the data in output value
	\*--------------------------------------------------------------------*/

 	ProWstringCopy (data.v.w, name, PRO_VALUE_UNUSED);
	status = PRO_TK_NO_ERROR;
	return status;

}

/*====================================================================*\
FUNCTION: UserDBSObjectTypeGet()
PURPOSE:  Get the object type loaded through Dbatch.
\*====================================================================*/
ProError UserDBSObjectTypeGet(ProArgument* input_arguments, ProName label, int* object_type)
{
	ProValueData data;
	char  model_type[PRO_NAME_SIZE];
	int length;
	ProError status;
	
	/*--------------------------------------------------------------------*\
	Get the value of argument
	\*--------------------------------------------------------------------*/
	
	status = ProArgumentByLabelGet(input_arguments, label, &data);
	
	if (status != PRO_TK_NO_ERROR)
    	return status;
	
	/*--------------------------------------------------------------------*\
	Data will always be of wstring type
	\*--------------------------------------------------------------------*/

	if (data.type != PRO_VALUE_TYPE_WSTRING)
	{
    		status = PRO_TK_INVALID_TYPE;
		return status;
	}
	
	ProWstringLengthGet (data.v.w, &length);
	
	if (length > PRO_NAME_SIZE -1)
	{
		status = PRO_TK_LINE_TOO_LONG;
		return status;
	}
	
	/*--------------------------------------------------------------------*\
	Copy the data in output value
	\*--------------------------------------------------------------------*/
	
	ProWstringToString (model_type,data.v.w);
	
	*object_type = atoi(model_type);
	
	status = PRO_TK_NO_ERROR;
	
	return status;
}
#undef MSGFIL