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


#include "ProToolkit.h"
#include "ProFeature.h"
#include "ProElemId.h"
#include "ProStdSection.h"
#include "ProFeatType.h"
#include "ProFeatForm.h"
#include "ProSelection.h"
#include "ProSection.h"
#include "ProSweep.h"
#include <ProSolid.h>

static ProFileName message_file; 
static ProSelection *references1; 
static ProError 	status; 

#define C_LOG(a) ProTKPrintf ("Status for %s is = %d\n", a, status ); \
	ERROR_CHECK( a, "UgSweepCreate.c", status );

#define C_PRINT(a) ProTKPrintf ( "%s\n", a);

ProError UserSweepSectionAdd ( ProSection ); 
ProError UserSweepSpineAdd ( ProSection , ProSelection * ); 
ProError UserSecerrorPrint ( ProWSecerror *section_errors );

/*===============================================================*\
FUNCTION : UgSweepProtrCreate
PURPOSE  : Demonstrates the creation of the Simple Sweep Protrusion
\*===============================================================*/
ProError UgSweepProtrCreate()
{
  ProReference REPDEP_ref2;
  ProReference REPDEP_ref1;
  ProElement pro_e_feature_tree;
  ProElement pro_e_feature_type;
  ProElement pro_e_feature_form;
  ProElement pro_e_sweep_spine;
  ProElement pro_e_std_sec_setup;
  ProElement pro_e_std_sec_method;
  ProElement pro_e_std_section_plane;
  ProElement pro_e_std_sec_plane;
  ProElement pro_e_std_sec_plane_view_dir;
  ProElement pro_e_std_sec_plane_orient_dir;
  ProElement pro_e_std_sec_plane_orient_ref;
  ProElement pro_e_sweep_section; 
  ProValue	 value;
  ProValueData value_data;
  ProSelection *p_select;
  int 		    n_select;

  ProMdl    model_current;  
  ProModelitem model_item;
  ProSelection  model_selection; 
  ProFeature    created_feature; 
  ProErrorlist  feat_errors; 
  ProElement    created_elemtree; 
  ProElement    created_elemtree_after1st; 
  ProElempath       element_path; 
  ProElempathItem   element_path_item[2]; 
  ProElement        sketch_element; 
  ProSection              section;

  ProFeatureCreateOptions *create_options = 0;

  ProFeatureCreateOptions *redefine_options = 0;

  
  
  ProStringToWstring ( message_file, "msg_ug3dsketch.txt" ); 

  references1 = ( ProSelection *) calloc (2, sizeof (ProSelection)); 	    
 
  /*---------------------------------------------------------------*\
    Populating root element PRO_E_FEATURE_TREE 
  \*---------------------------------------------------------------*/
  C_PRINT( " *** Processing Element PRO_E_FEATURE_TREE *** " );
  status = ProElementAlloc ( PRO_E_FEATURE_TREE, &pro_e_feature_tree); 
  C_LOG( " ProElementAlloc " );

  /*---------------------------------------------------------------*\
    Populating element PRO_E_FEATURE_TYPE 
  \*---------------------------------------------------------------*/
  C_PRINT( " *** Processing Element PRO_E_FEATURE_TYPE *** " );
  status = ProElementAlloc ( PRO_E_FEATURE_TYPE, &pro_e_feature_type);
  C_LOG( " PRO_E_FEATURE_TYPE ProElementAlloc " );
  status = ProElementIntegerSet(pro_e_feature_type,PRO_FEAT_PROTRUSION);
  C_LOG( " ProElementIntegerSet" );
  status = ProElemtreeElementAdd ( pro_e_feature_tree, NULL, 
												pro_e_feature_type );
  C_LOG( " ProElemtreeElementAdd" );

  /*---------------------------------------------------------------*\
    Populating element PRO_E_FEATURE_FORM 
  \*---------------------------------------------------------------*/
  C_PRINT( " *** Processing Element PRO_E_FEATURE_FORM *** " );
  status = ProElementAlloc ( PRO_E_FEATURE_FORM, &pro_e_feature_form );
  C_LOG( " PRO_E_FEATURE_FORM ProElementAlloc " );
  status = ProElementIntegerSet(pro_e_feature_form,PRO_SWEEP);
  C_LOG( " ProElementIntegerSet" );
  status = ProElemtreeElementAdd ( pro_e_feature_tree, NULL, 
												pro_e_feature_form );
  C_LOG( " ProElemtreeElementAdd" );

  /*---------------------------------------------------------------*\
    Populating element PRO_E_SWEEP_SPINE 
  \*---------------------------------------------------------------*/
  C_PRINT( " *** Processing Element PRO_E_SWEEP_SPINE *** " );
  status = ProElementAlloc ( PRO_E_SWEEP_SPINE, &pro_e_sweep_spine );
  C_LOG( " PRO_E_SWEEP_SPINE ProElementAlloc" );
  status = ProElemtreeElementAdd ( pro_e_feature_tree, NULL, 
											pro_e_sweep_spine  );
  C_LOG( " ProElemtreeElementAdd" );

  /*---------------------------------------------------------------*\
    Populating element PRO_E_SWEEP_SPINE 
			-> PRO_E_STD_SEC_SETUP
  \*---------------------------------------------------------------*/
  C_PRINT( " *** Processing Element PRO_E_STD_SEC_SETUP *** " );
  status = ProElementAlloc ( PRO_E_STD_SEC_SETUP, 
										&pro_e_std_sec_setup );
  C_LOG( " PRO_E_STD_SEC_SETUP ProElementAlloc" );
  status = ProElemtreeElementAdd ( pro_e_sweep_spine, NULL, 
											pro_e_std_sec_setup  );
  C_LOG( " ProElemtreeElementAdd" );

  /*---------------------------------------------------------------*\
    Populating element PRO_E_STD_SEC_SETUP 
			-> PRO_E_STD_SEC_METHOD
  \*---------------------------------------------------------------*/ 
  C_PRINT( " *** Processing Element PRO_E_STD_SEC_METHOD *** " );
  status = ProElementAlloc ( PRO_E_STD_SEC_METHOD, 
									&pro_e_std_sec_method );
  C_LOG( " PRO_E_STD_SEC_METHOD ProElementAlloc " );
  status = ProElementIntegerSet(pro_e_std_sec_method,PRO_SEC_SKETCH);
  C_LOG( " ProElementIntegerSet" );
  status = ProElemtreeElementAdd ( pro_e_std_sec_setup, NULL, 
										pro_e_std_sec_method );
  C_LOG( " ProElemtreeElementAdd" );
 
    /* 1st section */ 
  /*---------------------------------------------------------------*\
    Populating element PRO_E_STD_SEC_SETUP 
			-> PRO_E_STD_SECTION_PLANE 
  \*---------------------------------------------------------------*/
  C_PRINT( " *** Processing Element PRO_E_STD_SECTION_PLANE *** " );
  status = ProElementAlloc ( PRO_E_STD_SECTION_PLANE, 
									&pro_e_std_section_plane );
  C_LOG( " PRO_E_STD_SECTION_PLANE ProElementAlloc" );
  status = ProElemtreeElementAdd ( pro_e_std_sec_setup, NULL, 
											pro_e_std_section_plane  );
  C_LOG( " ProElemtreeElementAdd" );


  /*---------------------------------------------------------------*\
    Populating element PRO_E_STD_SEC_SETUP 
			-> PRO_E_STD_SEC_PLANE 
  \*---------------------------------------------------------------*/
  C_PRINT( " *** Processing Element PRO_E_STD_SEC_PLANE *** " );
  status = ProMessageDisplay ( message_file, 
								"Select Surface for sketch placement");
  C_LOG( " ProMessageDisplay"  );

  status = ProSelect ( "datum,surface,sldface,qltface", 1, NULL, NULL, 
									NULL, NULL, &p_select, &n_select );
  C_LOG( " ProSelect" );
  if ( n_select <= 0 ) return -1; 
  else 
    {
		status = ProSelectionCopy ( p_select[0], &references1[0]); 
		C_LOG( " ProSelectionCopy" );
    }

  status = ProElementAlloc ( PRO_E_STD_SEC_PLANE, 
											&pro_e_std_sec_plane );
  C_LOG( " PRO_E_STD_SEC_PLANE ProElementAlloc " );
  status = ProSelectionToReference( p_select[0],&REPDEP_ref1 );
  status = ProElementReferenceSet(pro_e_std_sec_plane,REPDEP_ref1);
  C_LOG( " ProElementReferenceSet" );
  status = ProElemtreeElementAdd ( pro_e_std_section_plane, NULL, 
											pro_e_std_sec_plane );
  C_LOG( " ProElemtreeElementAdd" );
    
   
  /*---------------------------------------------------------------*\
    Populating element PRO_E_STD_SEC_SETUP 
			-> PRO_E_STD_SEC_PLANE_VIEW_DIR  
  \*---------------------------------------------------------------*/
  C_PRINT( " *** Processing Element PRO_E_STD_SEC_PLANE_VIEW_DIR *** " );
  status = ProElementAlloc ( PRO_E_STD_SEC_PLANE_VIEW_DIR, 
									&pro_e_std_sec_plane_view_dir );
  C_LOG( " PRO_E_STD_SEC_PLANE_VIEW_DIR ProElementAlloc " );
  status = ProElementIntegerSet(pro_e_std_sec_plane_view_dir,1);
  C_LOG( " ProElementIntegerSet" );
  status = ProElemtreeElementAdd ( pro_e_std_section_plane, NULL, 
									pro_e_std_sec_plane_view_dir );
  C_LOG( " ProElemtreeElementAdd" );

  /*---------------------------------------------------------------*\
    Populating element PRO_E_STD_SEC_SETUP 
			-> PRO_E_STD_SEC_PLANE_ORIENT_DIR 
  \*---------------------------------------------------------------*/    
  C_PRINT( " *** Processing Element PRO_E_STD_SEC_PLANE_ORIENT_DIR *** " );
  status = ProElementAlloc ( PRO_E_STD_SEC_PLANE_ORIENT_DIR, 
								&pro_e_std_sec_plane_orient_dir );
  C_LOG( " PRO_E_STD_SEC_PLANE_ORIENT_DIR ProElementAlloc " );
  status = ProElementIntegerSet(pro_e_std_sec_plane_orient_dir,1);
  C_LOG( " ProElementIntegerSet" );
  status = ProElemtreeElementAdd ( pro_e_std_section_plane, NULL, 
									pro_e_std_sec_plane_orient_dir );
  C_LOG( " ProElemtreeElementAdd" );

  /*---------------------------------------------------------------*\
    Populating element PRO_E_STD_SEC_SETUP 
			-> PRO_E_STD_SEC_PLANE_ORIENT_REF 
  \*---------------------------------------------------------------*/
  C_PRINT( " *** Processing Element PRO_E_STD_SEC_PLANE_ORIENT_REF *** " );
  status = ProMessageDisplay ( message_file, 
								"Select Surface for sketch orientation");
  C_LOG( " ProMessageDisplay"  );
  status = ProSelect ( "datum,surface,sldface,qltface", 1, NULL, NULL, 
									NULL, NULL, &p_select, &n_select );
  C_LOG( " ProSelect" );
  if ( n_select <= 0 ) return -1; 
  else 
	{
	  status = ProSelectionCopy ( p_select[0], &references1[1]); 
	  C_LOG( " ProSelectionCopy" );
	}
      
  status = ProElementAlloc ( PRO_E_STD_SEC_PLANE_ORIENT_REF, 
									&pro_e_std_sec_plane_orient_ref );
  C_LOG( " PRO_E_STD_SEC_PLANE_ORIENT_REF ProElementAlloc " );
  status = ProSelectionToReference( p_select[0],&REPDEP_ref2 );
  status = ProElementReferenceSet(pro_e_std_sec_plane_orient_ref,REPDEP_ref2);
  C_LOG( " ProElementValueSet" );
  status = ProElemtreeElementAdd ( pro_e_std_section_plane, 
								NULL, pro_e_std_sec_plane_orient_ref );
  C_LOG( " ProElemtreeElementAdd" );
 
/*---------------------------------------------------------------*\
	Populating element PRO_E_SWEEP_SECTION 
\*---------------------------------------------------------------*/
  C_PRINT( " *** Processing Element PRO_E_SWEEP_SECTION *** " );
  status = ProElementAlloc ( PRO_E_SWEEP_SECTION, &pro_e_sweep_section );
  C_LOG( " PRO_E_SWEEP_SECTION ProElementAlloc" );
  status = ProElemtreeElementAdd ( pro_e_feature_tree, NULL, 
											pro_e_sweep_section  );
  C_LOG( " ProElemtreeElementAdd" );
  
  C_PRINT( " *** Processing Element PRO_E_STD_SEC_SETUP *** " );
  status = ProElementAlloc ( PRO_E_STD_SEC_SETUP, &pro_e_std_sec_setup );
  C_LOG( " PRO_E_STD_SEC_SETUP ProElementAlloc" );
  status = ProElemtreeElementAdd ( pro_e_sweep_section, NULL, 
												pro_e_std_sec_setup  );
  C_LOG( " ProElemtreeElementAdd" );
 
/*--------------------------------------------------------------------*\
	Create the incomplete feature so Pro/ENGINEER allocates the 
	section handles.
\*--------------------------------------------------------------------*/
  status = ProMdlCurrentGet( &model_current );
  C_LOG( " ProMdlCurrentGet " );
  
  status = ProMdlToModelitem( model_current, &model_item );
  C_LOG( " ProMdlToModelitem " );
  
  status = ProSelectionAlloc( NULL, &model_item, &model_selection );
  C_LOG( " ProSelectionAlloc " );
  
  status = ProArrayAlloc(1,sizeof(ProFeatureCreateOptions),
    1, (ProArray*)&create_options);

  create_options[0]= PRO_FEAT_CR_INCOMPLETE_FEAT;

  status = ProFeatureWithoptionsCreate ( model_selection, pro_e_feature_tree,
    create_options, PRO_REGEN_NO_FLAGS, &created_feature, &feat_errors );
  C_LOG( " ProFeatureCreate " );

  status = ProArrayFree((ProArray*)&create_options);
  
  if ( status != PRO_TK_NO_ERROR ) 
    return status; 
  
/*--------------------------------------------------------------------*\
	Extract the current feature element tree
\*--------------------------------------------------------------------*/
  status = ProFeatureElemtreeExtract (&created_feature, NULL, PRO_FEAT_EXTRACT_NO_OPTS,
		 &created_elemtree);
  C_LOG ("ProFeatureElemtreeExtract()");
  
  element_path_item[0].type = PRO_ELEM_PATH_ITEM_TYPE_ID;
  element_path_item[0].path_item.elem_id = PRO_E_SWEEP_SPINE; 
  element_path_item[1].type = PRO_ELEM_PATH_ITEM_TYPE_ID;
  element_path_item[1].path_item.elem_id = PRO_E_SKETCHER; 
  
  status = ProElempathAlloc ( &element_path ); 
  C_LOG( " ProElempathAlloc " );
  
  status = ProElempathDataSet ( element_path, element_path_item, 2 ); 
  C_LOG( " ProElempathDataSet " );
  
  status = ProElemtreeElementGet ( created_elemtree, 
                   element_path, &sketch_element ); 
  C_LOG( " ProElemtreeElementGet " );

  ProElempathFree ( &element_path );
  
  status = ProElementSpecialvalueGet(sketch_element, NULL, (ProAppData *) &section);
  C_LOG (" ProElementSpecialvalueGet PRO_E_SKETCHER ");
  
/*--------------------------------------------------------------------*\
	Add the trajectory sketch and partially redefine the feature
\*--------------------------------------------------------------------*/
  status = UserSweepSpineAdd ( ( ProSection ) (section), 
                ( ProSelection * )references1); 
  C_LOG( " UserSweepSpineAdd " ); 
  
  status = ProArrayAlloc(1,sizeof(ProFeatureCreateOptions),
    1, (ProArray*)&redefine_options);

  redefine_options[0]= PRO_FEAT_CR_DEFINE_MISS_ELEMS;

  status = ProFeatureWithoptionsRedefine ( NULL, &created_feature, created_elemtree,
    redefine_options, PRO_REGEN_NO_FLAGS, &feat_errors );
  C_LOG( " ProFeatureRedefine Spine " );

/*--------------------------------------------------------------------*\
	Extract the new feature element tree.  Now the sweep section sketcher
	pointer is available for use.
\*--------------------------------------------------------------------*/
  status = ProFeatureElemtreeExtract (&created_feature, NULL, PRO_FEAT_EXTRACT_NO_OPTS,
		 &created_elemtree_after1st);
  C_LOG ("ProFeatureElemtreeExtract()");

  element_path_item[0].type = PRO_ELEM_PATH_ITEM_TYPE_ID;
  element_path_item[0].path_item.elem_id = PRO_E_SWEEP_SECTION; 
  element_path_item[1].type = PRO_ELEM_PATH_ITEM_TYPE_ID;
  element_path_item[1].path_item.elem_id = PRO_E_SKETCHER; 
  
  status = ProElempathAlloc ( &element_path ); 
  C_LOG( " ProElempathAlloc " );
  
  status = ProElempathDataSet ( element_path, element_path_item, 2 ); 
  C_LOG( " ProElempathDataSet " );
  
  status = ProElemtreeElementGet ( created_elemtree_after1st, 
               element_path, &sketch_element ); 
  C_LOG( " ProElemtreeElementGet " );

  ProElempathFree ( &element_path );
 
 status = ProElementSpecialvalueGet(sketch_element, NULL, (ProAppData *) &section);
  C_LOG (" ProElementSpecialvalueGet PRO_E_SKETCHER ");

  
/*--------------------------------------------------------------------*\
	Add the section sketch and finish the feature.
\*--------------------------------------------------------------------*/
  status = UserSweepSectionAdd ( section ); 
  C_LOG( " PTTestSection2DAdd " );

  status = ProFeatureWithoptionsRedefine ( NULL, &created_feature, created_elemtree_after1st,
    redefine_options, PRO_REGEN_NO_FLAGS, &feat_errors );

  C_LOG( " ProFeatureWithoptionsRedefine " );

  status = ProArrayFree((ProArray*)&redefine_options);

/*--------------------------------------------------------------------*\
	Free memory allocated by this function.
\*--------------------------------------------------------------------*/
  status = ProElementFree ( &pro_e_feature_tree );
  C_LOG( " ProElementFree " );
  
  status = ProFeatureElemtreeFree ( &created_feature, created_elemtree); 
  C_LOG( " ProFeatureElemtreeFree " );

  status = ProFeatureElemtreeFree ( &created_feature, created_elemtree_after1st); 
  C_LOG( " ProFeatureElemtreeFree " );

  free (references1);
 
  return status; 
}

#undef C_LOG
#undef C_PRINT