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



/*---------------------- Pro/Toolkit Includes ------------------------*/
#include "ProToolkit.h"
#include "ProFeature.h"
#include "ProElemId.h"
#include "ProExtrude.h"
#include "ProModFeat.h"
#include "ProStdSection.h"
#include "ProElement.h"
#include "ProElempath.h"
#include "ProFeatType.h"
#include "ProFeatForm.h"
#include "ProSelection.h"
#include "ProSection.h"

#include "ProRevolve.h"

static ProFileName message_file; 

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

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

/*===============================================================*\
FUNCTION : UserSktRevolveProtrusionExtSkt()
PURPOSE  : Create a revolved protrustion with external sketch
\*===============================================================*/
ProError UserSktRevolveProtrusionExtSkt()
{
  ProErrorlist            errors;
  ProMdl                  model;
  ProModelitem            model_item;
  ProSelection            model_sel;
  ProFeature              feature;
  ProFeatureCreateOptions *opts = 0;
  ProElempath             path;
  ProElempathItem         path_items[2];
  ProSection              section;
  ProAsmcomppath          comp_path;
  ProAsmcomppath          *p_comp_path = NULL;

  ProElement pro_e_feature_tree;
  ProElement pro_e_feature_type;
  ProElement pro_e_feature_form;
  ProElement pro_e_ext_surf_cut_solid_type;
  ProElement pro_e_remove_material;
  ProElement pro_e_feat_form_is_thin;

  ProElement pro_e_rev_angle;
  ProElement pro_e_rev_angle_from;
  ProElement pro_e_rev_angle_from_type;
  ProElement pro_e_rev_angle_from_val;
  ProElement pro_e_rev_angle_to;
  ProElement pro_e_rev_angle_to_type;
  ProElement pro_e_rev_angle_to_val;
 
  /* External Sketch */ 
  ProElement pro_e_std_section;
  ProElement pro_e_use_sketch ;

  /* External Axis */ 
  ProElement pro_e_revolve_axis;
  ProElement pro_e_revolve_axis_opt ;
  
  ProError 	status;
  ProSelection * p_select;
  int 		n_select;

  ProReference external_sketch_ref; 
  ProReference external_axis_ref; 
  
  ProStringToWstring ( message_file, "msg_ugfeatcreat.txt" ); 

  log_file = PTApplsUnicodeFopen ( "ug_sketched_curve.log", "w" ); 

  status = ProMdlCurrentGet (&model);
  if ( status != PRO_TK_NO_ERROR ) return ( status );
  
  /*---------------------------------------------------------------*\
    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_FORM
  \*---------------------------------------------------------------*/

  C_PRINT( " *** Processing Element PRO_E_FEATURE_FORM *** " );
  status = ProElementAlloc ( PRO_E_FEATURE_FORM, &pro_e_feature_form );
  C_LOG( " ProElementAlloc " );
  status = ProElementIntegerSet ( pro_e_feature_form, PRO_REVOLVE );
  C_LOG( " ProElementIntegerSet" );
  status = ProElemtreeElementAdd ( pro_e_feature_tree, NULL, pro_e_feature_form );
  C_LOG( " ProElemtreeElementAdd" );

  /*---------------------------------------------------------------*\
    Populating element PRO_E_EXT_SURF_CUT_SOLID_TYPE
  \*---------------------------------------------------------------*/
  
  C_PRINT( " *** Processing Element PRO_E_EXT_SURF_CUT_SOLID_TYPE *** " );
  status = ProElementAlloc ( PRO_E_EXT_SURF_CUT_SOLID_TYPE, &pro_e_ext_surf_cut_solid_type );
  C_LOG( " ProElementAlloc " );
  status = ProElementIntegerSet ( pro_e_ext_surf_cut_solid_type, PRO_REV_FEAT_TYPE_SOLID );
  C_LOG( " ProElementIntegerSet" );
  status = ProElemtreeElementAdd ( pro_e_feature_tree, NULL, pro_e_ext_surf_cut_solid_type );
  C_LOG( " ProElemtreeElementAdd" );
 
  /*---------------------------------------------------------------*\
    Populating  element PRO_E_REMOVE_MATERIAL
  \*---------------------------------------------------------------*/

  C_PRINT( " *** Processing Element PRO_E_REMOVE_MATERIAL *** " );
  status = ProElementAlloc ( PRO_E_REMOVE_MATERIAL, &pro_e_remove_material );
  C_LOG( " ProElementAlloc " );
  status = ProElementIntegerSet ( pro_e_remove_material, PRO_REV_MATERIAL_ADD );
  C_LOG( " ProElementIntegerSet" );
  status = ProElemtreeElementAdd ( pro_e_feature_tree, NULL, pro_e_remove_material );
  C_LOG( " ProElemtreeElementAdd" );
  
  /*---------------------------------------------------------------*\
    Populating  element PRO_E_FEAT_FORM_IS_THIN
  \*---------------------------------------------------------------*/

  C_PRINT( " *** Processing Element PRO_E_FEAT_FORM_IS_THIN *** " );
  status = ProElementAlloc ( PRO_E_FEAT_FORM_IS_THIN, &pro_e_feat_form_is_thin );
  C_LOG( " ProElementAlloc " );
  status = ProElementIntegerSet ( pro_e_feat_form_is_thin, PRO_REV_FEAT_FORM_NO_THIN );
  C_LOG( " ProElementIntegerSet" );
  status = ProElemtreeElementAdd ( pro_e_feature_tree, NULL, pro_e_feat_form_is_thin );
  C_LOG( " ProElemtreeElementAdd" );

  /*---------------------------------------------------------------*\
    Populating  compound element PRO_E_STD_REV_ANGLE
  \*---------------------------------------------------------------*/
  C_PRINT( " *** Processing Element PRO_E_REV_ANGLE *** " );
  status = ProElementAlloc ( PRO_E_REV_ANGLE, &pro_e_rev_angle );
  C_LOG( " ProElementAlloc" );
  status = ProElemtreeElementAdd ( pro_e_feature_tree, NULL, pro_e_rev_angle  );
  C_LOG( " ProElemtreeElementAdd" );

  /*---------------------------------------------------------------*\
    Populating  element PRO_E_REV_ANGLE
			-> PRO_E_REV_ANGLE_FROM
  \*---------------------------------------------------------------*/
  C_PRINT( " *** Processing Element PRO_E_REV_ANGLE_FROM *** " );
  status = ProElementAlloc ( PRO_E_REV_ANGLE_FROM, &pro_e_rev_angle_from );
  C_LOG( " ProElementAlloc" );
  status = ProElemtreeElementAdd ( pro_e_rev_angle, NULL, pro_e_rev_angle_from  );
  C_LOG( " ProElemtreeElementAdd" );

  /*---------------------------------------------------------------*\
    Populating  element PRO_E_REV_ANGLE
			-> PRO_E_REV_ANGLE_FROM
			   -> PRO_E_REV_ANGLE_FROM_TYPE
  \*---------------------------------------------------------------*/
  C_PRINT( " *** Processing Element PRO_E_REV_ANGLE_FROM_TYPE *** " );
  status = ProElementAlloc ( PRO_E_REV_ANGLE_FROM_TYPE, &pro_e_rev_angle_from_type );
  C_LOG( " ProElementAlloc " );
  status = ProElementIntegerSet ( pro_e_rev_angle_from_type, PRO_REV_ANG_FROM_NONE );
  C_LOG( " ProElementIntegerSet" );
  status = ProElemtreeElementAdd ( pro_e_rev_angle_from, NULL, pro_e_rev_angle_from_type );
  C_LOG( " ProElemtreeElementAdd" );

  /*---------------------------------------------------------------*\
    Populating  element PRO_E_REV_ANGLE
			-> PRO_E_REV_ANGLE_TO
  \*---------------------------------------------------------------*/
  C_PRINT( " *** Processing Element PRO_E_REV_ANGLE_TO *** " );
  status = ProElementAlloc ( PRO_E_REV_ANGLE_TO, &pro_e_rev_angle_to );
  C_LOG( " ProElementAlloc" );
  status = ProElemtreeElementAdd ( pro_e_rev_angle, NULL, pro_e_rev_angle_to  );
  C_LOG( " ProElemtreeElementAdd" );
  
  /*---------------------------------------------------------------*\
    Populating  element PRO_E_REV_ANGLE
			-> PRO_E_REV_ANGLE_TO
			   -> PRO_E_REV_ANGLE_TO_TYPE
  \*---------------------------------------------------------------*/
  C_PRINT( " *** Processing Element PRO_E_REV_ANGLE_TO_TYPE *** " );
  status = ProElementAlloc ( PRO_E_REV_ANGLE_TO_TYPE, &pro_e_rev_angle_to_type );
  C_LOG( " ProElementAlloc " );
  status = ProElementIntegerSet ( pro_e_rev_angle_to_type, PRO_REV_ANG_TO_ANGLE );
  C_LOG( " ProElementIntegerSet" );
  status = ProElemtreeElementAdd ( pro_e_rev_angle_to, NULL, pro_e_rev_angle_to_type );
  C_LOG( " ProElemtreeElementAdd" );

  /*---------------------------------------------------------------*\
    Populating  element PRO_E_REV_ANGLE
			-> PRO_E_REV_ANGLE_TO
			   -> PRO_E_REV_ANGLE_TO_VAL
  \*---------------------------------------------------------------*/
  C_PRINT( " *** Processing Element PRO_E_REV_ANGLE_TO_VAL *** " );
  status = ProElementAlloc ( PRO_E_REV_ANGLE_TO_VAL, &pro_e_rev_angle_to_val );
  C_LOG( " ProElementAlloc " );
  status = ProElementDoubleSet ( pro_e_rev_angle_to_val, 120.000000 );
  C_LOG( " ProElementDoubleSet" );
  status = ProElemtreeElementAdd ( pro_e_rev_angle_to, NULL, pro_e_rev_angle_to_val );
  C_LOG( " ProElemtreeElementAdd" );
 
  /*---------------------------------------------------------------*\
    Populating  element PRO_E_STD_SECTION
  \*---------------------------------------------------------------*/

  C_PRINT( " *** Processing Element PRO_E_STD_SECTION *** " );
  status = ProElementAlloc ( PRO_E_STD_SECTION, &pro_e_std_section );
  C_LOG( " ProElementAlloc" );
  status = ProElemtreeElementAdd ( pro_e_feature_tree, NULL, 
		pro_e_std_section  );
  C_LOG( " ProElemtreeElementAdd" );

  /*---------------------------------------------------------------*\
    Populating element PRO_E_STD_SECTION 
			-> PRO_E_SEC_USE_SKETCH
  \*---------------------------------------------------------------*/
  
  C_PRINT( " *** Processing Element PRO_E_SEC_USE_SKETCH *** " );
  status = ProMessageDisplay ( message_file, "USER Select Sketch :" ); 
  C_LOG( " ProMessageDisplay"  );

  status = ProSelect ( "feature", 1, NULL, NULL, 
		NULL, NULL, &p_select, &n_select );
  C_LOG( " ProSelect" );
  if ( n_select <= 0 ) return -1; 
  else
    {
      status = ProSelectionToReference ( p_select[0], &external_sketch_ref );
      C_LOG (" ProSelectionToReference ");
    }
  status = ProElementAlloc ( PRO_E_SEC_USE_SKETCH, &pro_e_use_sketch );
  C_LOG( " ProElementAlloc " );

  status = ProElementReferenceSet ( pro_e_use_sketch, external_sketch_ref );
  C_LOG( " ProElementReferenceSet" );

  status = ProElemtreeElementAdd ( pro_e_std_section, NULL, 
		pro_e_use_sketch );
  C_LOG( " ProElemtreeElementAdd" );

  /*---------------------------------------------------------------*\
    Populating  element PRO_E_REVOLVE_AXIS_OPT
  \*---------------------------------------------------------------*/
  C_PRINT( " *** Processing Element PRO_E_REVOLVE_AXIS_OPT *** " );
  status = ProElementAlloc ( PRO_E_REVOLVE_AXIS_OPT, &pro_e_revolve_axis_opt );
  C_LOG( " ProElementAlloc " );
  status = ProElementIntegerSet ( pro_e_revolve_axis_opt, PRO_REV_AXIS_EXT_REF );
  C_LOG( " ProElementIntegerSet" );
  status = ProElemtreeElementAdd ( pro_e_feature_tree, NULL, pro_e_revolve_axis_opt );
  C_LOG( " ProElemtreeElementAdd" );

  /*---------------------------------------------------------------*\
    Populating element PRO_E_REVOLVE_AXIS 
  \*---------------------------------------------------------------*/
  
  C_PRINT( " *** Processing Element PRO_E_REVOLVE_AXIS *** " );
  status = ProMessageDisplay ( message_file, "USER Select Revolve Axis :");
  C_LOG( " ProMessageDisplay"  );

  status = ProSelect ( "edge,axis", 1, NULL, NULL, 
		NULL, NULL, &p_select, &n_select );
  C_LOG( " ProSelect" );
  if ( n_select <= 0 ) return -1; 
  else
    {
      status = ProSelectionToReference ( p_select[0], &external_axis_ref );
      C_LOG (" ProSelectionToReference ");
    }
  status = ProElementAlloc ( PRO_E_REVOLVE_AXIS, &pro_e_revolve_axis );
  C_LOG( " ProElementAlloc " );

  status = ProElementReferenceSet ( pro_e_revolve_axis, external_axis_ref );
  C_LOG( " ProElementReferenceSet" );

  status = ProElemtreeElementAdd ( pro_e_feature_tree, NULL, 
		pro_e_revolve_axis );
  
  /*---------------------------------------------------------------*\
    Creating feature in the current model.
  \*---------------------------------------------------------------*/
  status = ProMdlToModelitem( model, &model_item ); 
  status = ProSelectionAlloc (p_comp_path, &model_item,
			   &model_sel);
  

  status = ProArrayAlloc(1,sizeof(ProFeatureCreateOptions),
    1, (ProArray*)&opts);

  opts[0]= PRO_FEAT_CR_DEFINE_MISS_ELEMS;

  status = ProFeatureWithoptionsCreate (model_sel, pro_e_feature_tree,
    opts, PRO_REGEN_NO_FLAGS, &feature, &errors);
  C_LOG (" ProFeatureWithoptionsCreate"); 

  status = ProArrayFree((ProArray*)&opts);
  
/*---------------------------------------------------------------*\
    Free up the allocated memory.
\*---------------------------------------------------------------*/
  
  status = ProElementFree (&pro_e_feature_tree ); 
  C_LOG (" ProElementFree"); 
  
  return (status);
}

#undef C_LOG
#undef C_PRINT