/*
	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 "ProModelitem.h"

#include "ProSrfcollection.h"
#include "ProCrvcollection.h"
#include "ProRound.h"
#include "ProChamfer.h"

static ProFileName message_file; 

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

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

/*===============================================================*\
FUNCTION : UserEdgeChamferCreate()
PURPOSE  : Function for creation of Edge Chamfer features.
\*===============================================================*/
ProError UserEdgeChamferCreate()
{
  ProErrorlist            errors;
  ProMdl                  model;
  ProSelection            model_sel;
  ProFeature              feature;
  ProFeatureCreateOptions *opts = 0;
  ProElempath             path;
  ProElempathItem         path_items[2];
  ProSection              section;
  ProAsmcomppath          comp_path;
  ProAsmcomppath          *p_comp_path = NULL;

  ProCollection collection;
  ProCrvcollinstr instr;
  ProModelitem model_item;
  ProReference reference;
  ProName wide_string; 

  ProElement pro_e_feature_tree;
  ProElement pro_e_feature_type;
  ProElement pro_e_std_feature_name;
  ProElement pro_e_rndch_sets;
  ProElement pro_e_rndch_set;
  ProElement pro_e_rndch_dimensional_schema;
  ProElement pro_e_rndch_chamfer_shape;
  ProElement pro_e_rndch_shape_options;
  ProElement pro_e_rndch_variable_radius;
  ProElement pro_e_rndch_compound_conic;
  ProElement pro_e_rndch_conic_type;
  ProElement pro_e_rndch_conic_value;
  ProElement pro_e_rndch_conic_dep_opt;
  ProElement pro_e_rndch_references;
  ProElement pro_e_rndch_reference_type;
  ProElement pro_e_std_curve_collection_appl;
  ProElement pro_e_rndch_compound_spine;
  ProElement pro_e_rndch_ball_spine;
  ProElement pro_e_rndch_compound_ext_options;
  ProElement pro_e_rndch_auto_blend;
  ProElement pro_e_rndch_radii;
  ProElement pro_e_rndch_radius;
  ProElement pro_e_rndch_leg1;
  ProElement pro_e_rndch_leg_type;
  ProElement pro_e_rndch_leg_value;
  ProElement pro_e_rndch_leg2;
  ProElement pro_e_rndch_attach_type;
  ProElement pro_e_rndch_transitions;

  ProStringToWstring ( message_file, "utilities.txt" ); 

  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_TYPE 
  \*---------------------------------------------------------------*/
  C_PRINT( " *** Processing Element PRO_E_FEATURE_TYPE *** " );
  status = ProElementAlloc ( PRO_E_FEATURE_TYPE, &pro_e_feature_type );
  C_LOG( " ProElementAlloc " );
  status = ProElementIntegerSet ( pro_e_feature_type, PRO_FEAT_CHAMFER ); 
  C_LOG( " ProElementIntegerSet" );
  status = ProElemtreeElementAdd ( pro_e_feature_tree, NULL, pro_e_feature_type );
  C_LOG( " ProElemtreeElementAdd" );

  /*---------------------------------------------------------------*\
    Populating element PRO_E_STD_FEATURE_NAME 
    - Optional 
  \*---------------------------------------------------------------*/
  C_PRINT( " *** Processing Element PRO_E_STD_FEATURE_NAME *** " );
  status = ProElementAlloc ( PRO_E_STD_FEATURE_NAME, &pro_e_std_feature_name );
  C_LOG( " ProElementAlloc " );
  ProStringToWstring ( wide_string, "CHAMFER_ID_XXX" );
  status = ProElementWstringSet (  pro_e_std_feature_name, wide_string );
  C_LOG( " ProElementWstringSet" );
  status = ProElemtreeElementAdd ( pro_e_feature_tree, NULL, pro_e_std_feature_name );
  C_LOG( " ProElemtreeElementAdd" );

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

  /*---------------------------------------------------------------*\
    Populating element PRO_E_RNDCH_SET 
  \*---------------------------------------------------------------*/
  C_PRINT( " *** Processing Element PRO_E_RNDCH_SET *** " );
  status = ProElementAlloc ( PRO_E_RNDCH_SET, &pro_e_rndch_set );
  C_LOG( " ProElementAlloc " );
  status = ProElemtreeElementAdd ( pro_e_rndch_sets, NULL, pro_e_rndch_set  );
  C_LOG( " ProElemtreeElementAdd" );

  /*---------------------------------------------------------------*\
    Populating element PRO_E_RNDCH_DIMENSIONAL_SCHEMA 
  \*---------------------------------------------------------------*/
  C_PRINT( " *** Processing Element PRO_E_RNDCH_DIMENSIONAL_SCHEMA *** " );
  status = ProElementAlloc ( PRO_E_RNDCH_DIMENSIONAL_SCHEMA, &pro_e_rndch_dimensional_schema );
  C_LOG( " ProElementAlloc " );
  status = ProElementIntegerSet ( pro_e_rndch_dimensional_schema, PRO_CHM_D_X_D ); 
  C_LOG( " ProElementIntegerSet" );
  status = ProElemtreeElementAdd ( pro_e_rndch_set, NULL, pro_e_rndch_dimensional_schema );
  C_LOG( " ProElemtreeElementAdd" );

  /*---------------------------------------------------------------*\
    Populating element PRO_E_RNDCH_CHAMFER_SHAPE 
  \*---------------------------------------------------------------*/
  C_PRINT( " *** Processing Element PRO_E_RNDCH_CHAMFER_SHAPE *** " );
  status = ProElementAlloc ( PRO_E_RNDCH_CHAMFER_SHAPE, &pro_e_rndch_chamfer_shape );
  C_LOG( " ProElementAlloc " );
  status = ProElementIntegerSet ( pro_e_rndch_chamfer_shape, PRO_CHM_OFFSET_SURFACE );
  C_LOG( " ProElementIntegerSet" );
  status = ProElemtreeElementAdd ( pro_e_rndch_set, NULL, pro_e_rndch_chamfer_shape );
  C_LOG( " ProElemtreeElementAdd" );

  /*---------------------------------------------------------------*\
    Populating element PRO_E_RNDCH_REFERENCES 
  \*---------------------------------------------------------------*/
  C_PRINT( " *** Processing Element PRO_E_RNDCH_REFERENCES *** " );
  status = ProElementAlloc ( PRO_E_RNDCH_REFERENCES, &pro_e_rndch_references );
  C_LOG( " ProElementAlloc " );
  status = ProElemtreeElementAdd ( pro_e_rndch_set, NULL, pro_e_rndch_references  );
  C_LOG( " ProElemtreeElementAdd" );

  /*---------------------------------------------------------------*\
    Populating element PRO_E_STD_CURVE_COLLECTION_APPL 
    - One by one curve collection for edges to be chamfered 
  \*---------------------------------------------------------------*/
  C_PRINT( " *** Processing Element PRO_E_STD_CURVE_COLLECTION_APPL *** " );
  status = ProElementAlloc ( PRO_E_STD_CURVE_COLLECTION_APPL, &pro_e_std_curve_collection_appl );
  C_LOG( " ProElementAlloc " );
  status = ProCrvcollectionAlloc ( &collection );
  C_LOG( " ProCrvcollectionAlloc" );
  status = ProCrvcollinstrAlloc ( PRO_CURVCOLL_ADD_ONE_INSTR, &instr ); 
  C_LOG( " ProCrvcollinstrAlloc" );
  {
    ProSelection *sel_array; 
    int n_sel_array; 

    ProTKPrintf(" Please select edge for CHAMFER  \n");
    status = ProMessageDisplay ( message_file, "USER Select reference." ); 
    C_LOG( " ProMessageDisplay" );
    status = ProSelect ( "edge,curve", 1, NULL, NULL, NULL, NULL, 
	&sel_array, &n_sel_array ); 
    C_LOG( " ProSelect" );

    if ( n_sel_array <= 0 ) 
      return PRO_TK_GENERAL_ERROR; 
    
    status = ProSelectionToReference ( sel_array[0], &reference ); 
    C_LOG( " ProSelectionToReference" );
  }
  status = ProCrvcollinstrReferenceAdd ( instr, reference );
  C_LOG( " ProCrvcollinstrReferenceAdd" );
  status = ProCrvcollectionInstructionAdd ( collection, instr );
  C_LOG( " ProCrvcollectionInstructionAdd" );
  status = ProCrvcollinstrAlloc ( PRO_CURVCOLL_ADD_TANGENT_INSTR, &instr ); 
  C_LOG( " ProCrvcollinstrAlloc" );
  status = ProCrvcollectionInstructionAdd ( collection, instr );
  C_LOG( " ProCrvcollectionInstructionAdd" );
  status = ProElementCollectionSet( pro_e_std_curve_collection_appl, collection );
  C_LOG( " ProElementCollectionSet " );
  status = ProElemtreeElementAdd ( pro_e_rndch_references, NULL, pro_e_std_curve_collection_appl );
  C_LOG( " ProElemtreeElementAdd" );

  /*---------------------------------------------------------------*\
    Populating element PRO_E_RNDCH_RADII 
  \*---------------------------------------------------------------*/
  C_PRINT( " *** Processing Element PRO_E_RNDCH_RADII *** " );
  status = ProElementAlloc ( PRO_E_RNDCH_RADII, &pro_e_rndch_radii );
  C_LOG( " ProElementAlloc " );
  status = ProElemtreeElementAdd ( pro_e_rndch_set, NULL, pro_e_rndch_radii  );
  C_LOG( " ProElemtreeElementAdd" );

  /*---------------------------------------------------------------*\
    Populating element PRO_E_RNDCH_RADIUS 
  \*---------------------------------------------------------------*/
  C_PRINT( " *** Processing Element PRO_E_RNDCH_RADIUS *** " );
  status = ProElementAlloc ( PRO_E_RNDCH_RADIUS, &pro_e_rndch_radius );
  C_LOG( " ProElementAlloc " );
  status = ProElemtreeElementAdd ( pro_e_rndch_radii, NULL, pro_e_rndch_radius  );
  C_LOG( " ProElemtreeElementAdd" );

  /*---------------------------------------------------------------*\
    Populating element PRO_E_RNDCH_LEG1 
  \*---------------------------------------------------------------*/
  C_PRINT( " *** Processing Element PRO_E_RNDCH_LEG1 *** " );
  status = ProElementAlloc ( PRO_E_RNDCH_LEG1, &pro_e_rndch_leg1 );
  C_LOG( " ProElementAlloc " );
  status = ProElemtreeElementAdd ( pro_e_rndch_radius, NULL, pro_e_rndch_leg1  );
  C_LOG( " ProElemtreeElementAdd" );

  /*---------------------------------------------------------------*\
    Populating element PRO_E_RNDCH_LEG_TYPE 
    ProRoundRadiusType - 
    + PRO_ROUND_RADIUS_TYPE_VALUE, 
    + PRO_ROUND_RADIUS_THROUGH_POINT
  \*---------------------------------------------------------------*/
  C_PRINT( " *** Processing Element PRO_E_RNDCH_LEG_TYPE *** " );
  status = ProElementAlloc ( PRO_E_RNDCH_LEG_TYPE, &pro_e_rndch_leg_type );
  C_LOG( " ProElementAlloc " );
  status = ProElementIntegerSet ( pro_e_rndch_leg_type, PRO_ROUND_RADIUS_TYPE_VALUE ); 
  C_LOG( " ProElementIntegerSet" );
  status = ProElemtreeElementAdd ( pro_e_rndch_leg1, NULL, pro_e_rndch_leg_type );
  C_LOG( " ProElemtreeElementAdd" );

  /*---------------------------------------------------------------*\
    Populating element PRO_E_RNDCH_LEG_VALUE 
  \*---------------------------------------------------------------*/
  C_PRINT( " *** Processing Element PRO_E_RNDCH_LEG_VALUE *** " );
  status = ProElementAlloc ( PRO_E_RNDCH_LEG_VALUE, &pro_e_rndch_leg_value );
  C_LOG( " ProElementAlloc " );
  status = ProElementDoubleSet (  pro_e_rndch_leg_value, 26.500000 );
  C_LOG( " ProElementDoubleSet" );
  status = ProElemtreeElementAdd ( pro_e_rndch_leg1, NULL, pro_e_rndch_leg_value );
  C_LOG( " ProElemtreeElementAdd" );

  /*---------------------------------------------------------------*\
    Populating element PRO_E_RNDCH_ATTACH_TYPE 
  \*---------------------------------------------------------------*/
  C_PRINT( " *** Processing Element PRO_E_RNDCH_ATTACH_TYPE *** " );
  status = ProElementAlloc ( PRO_E_RNDCH_ATTACH_TYPE, &pro_e_rndch_attach_type );
  C_LOG( " ProElementAlloc " );
  status = ProElementIntegerSet ( pro_e_rndch_attach_type, PRO_ROUND_ATTACHED ); 
  /* 0 :: Ref ProRoundAttachType :: ProRound.h  */ 
  C_LOG( " ProElementIntegerSet" );
  status = ProElemtreeElementAdd ( pro_e_feature_tree, NULL, pro_e_rndch_attach_type );
  C_LOG( " ProElemtreeElementAdd" );

  /*---------------------------------------------------------------*\
    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