/*
	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 "ProStdSection.h"
#include "ProElement.h"
#include "ProFeatType.h"
#include "ProFeatForm.h"
#include "ProSelection.h"
#include "ProHole.h"

/*---------------------- MACRO ---------------------------------------*/

/* UG_HOLE_LOG : Macro to log the calls to functions  
 inputs : 
	a - name of the function getting called 
	b - error return by the function called 
*/  
#define UG_HOLE_LOG( a, b )  ProTKPrintf(" Return value of function %s is %d\n", a, b ); 

/*---------------------- Function Prototypes -------------------------*/


/*------------------------- External Data ----------------------------*/

/*------------------------- Global Data -----------------------------*/


/*===============================================================*\
FUNCTION : ProDemoHoleCreate
PURPOSE  : Demonstrates the creation of a straight linear hole
\*===============================================================*/

ProError ProDemoHoleCreate()
{
ProError status; 

	ProElement feat_elemtree; 
        ProElement elem_feattype;
        ProElement elem_featform;

        ProElement elem_hle_com;
         ProElement elem_hle_type_new;
         ProElement elem_hle_stan_type;

         ProElement elem_diameter;

         ProElement elem_hole_std_depth;
          ProElement elem_hole_depth_to;
           ProElement elem_hole_depth_to_type;
           ProElement elem_ext_depth_to_value;
           ProElement elem_ext_depth_to_ref;
          ProElement elem_hole_depth_from;
           ProElement elem_hole_depth_from_type;
           ProElement elem_ext_depth_from_value;
           ProElement elem_ext_depth_from_ref;

        ProElement elem_hle_placement; 
         ProElement elem_hle_prim_ref; 
         ProElement elem_hle_pl_type;
         ProElement elem_hle_dim_ref1;
         ProElement elem_hle_dim_dist1;
         ProElement elem_hle_dim_ref2;
         ProElement elem_hle_dim_dist2;

	ProValue value; 
	ProValueData value_data; 

	ProSelection *p_selection; 
	int n_selection; 

	ProFeatureCreateOptions *options = 0;
	ProFeature created_feature;
	ProErrorlist p_errors;
	ProMdl model; 
	ProModelitem model_item; 
	ProSelection model_selection; 
	ProReference reference;

/* Start of Element Tree Creation */ 

/* Adding the root element */ 

	status = ProElementAlloc ( PRO_E_FEATURE_TREE, &feat_elemtree ); 

/* Adding the element for feature type */ 

	ProTKPrintf(" PRO_E_FEATURE_TYPE \n");
	ProTKPrintf(" ****************** \n");
        status = ProElementAlloc ( PRO_E_FEATURE_TYPE, &elem_feattype );
        UG_HOLE_LOG (" ProElementAlloc ", status);

		status = ProElementIntegerSet ( elem_feattype, PRO_FEAT_HOLE);
		UG_HOLE_LOG (" ProElementIntegerSet ", status ); 

		status = ProElemtreeElementAdd ( feat_elemtree, NULL, elem_feattype );
        UG_HOLE_LOG (" ProElemtreeElementAdd ", status);

/* Adding the element for feature form */ 

	ProTKPrintf(" PRO_E_FEATURE_FORM \n");
	ProTKPrintf(" ****************** \n");

	status = ProElementAlloc ( PRO_E_FEATURE_FORM , &elem_featform ); 

		status = ProElementIntegerSet ( elem_featform, PRO_HLE_TYPE_STRAIGHT);
		UG_HOLE_LOG (" ProElementIntegerSet ", status ); 

		status = ProElemtreeElementAdd ( feat_elemtree, NULL, elem_featform );
        UG_HOLE_LOG (" ProElemtreeElementAdd ", status);


/* Adding the common element for hole information  */ 

	ProTKPrintf(" PRO_E_HLE_COM \n");
	ProTKPrintf(" ****************** \n");

	status = ProElementAlloc ( PRO_E_HLE_COM, &elem_hle_com );
	UG_HOLE_LOG (" ProElementAlloc PRO_E_HLE_COM", status);

	status = ProElemtreeElementAdd ( feat_elemtree, NULL, elem_hle_com );
	
	UG_HOLE_LOG (" ProElemtreeElementAdd ", status);


/* Adding the element for hole type : Straight, Standard, Sketched */ 

	ProTKPrintf(" PRO_E_HLE_TYPE_NEW \n");
	ProTKPrintf(" ****************** \n");

	status = ProElementAlloc ( PRO_E_HLE_TYPE_NEW, &elem_hle_type_new );
	UG_HOLE_LOG (" ProElementAlloc PRO_E_HLE_TYPE_NEW ", status);

	status = ProElementIntegerSet ( elem_hle_type_new, PRO_HLE_NEW_TYPE_STRAIGHT);
	UG_HOLE_LOG (" ProElementIntegerSet ", status ); 

	status = ProElemtreeElementAdd ( elem_hle_com, NULL, elem_hle_type_new );
    UG_HOLE_LOG (" ProElemtreeElementAdd ", status);

/* Specifying the Diameter of the Hole */ 

	ProTKPrintf(" PRO_E_DIAMETER \n");
	ProTKPrintf(" ****************** \n");

	status = ProElementAlloc ( PRO_E_DIAMETER, &elem_diameter );
	UG_HOLE_LOG (" ProElementAlloc PRO_E_DIAMETER ", status);

	status = ProElementDoubleSet ( elem_diameter, (double) 100.0);
	UG_HOLE_LOG (" ProElementDoubleSet ", status ); 

	status = ProElemtreeElementAdd ( elem_hle_com, NULL, elem_diameter );
    UG_HOLE_LOG (" ProElemtreeElementAdd ", status);

/* Adding an element for the Standard Depth 

          |--PRO_E_HOLE_STD_DEPTH
          |    |--PRO_E_HOLE_DEPTH_TO
          |    |    |--PRO_E_HOLE_DEPTH_TO_TYPE
          |    |    |--PRO_E_EXT_DEPTH_TO_VALUE
          |    |    |--PRO_E_EXT_DEPTH_TO_REF
          |    |--PRO_E_HOLE_DEPTH_FROM
          |         |--PRO_E_HOLE_DEPTH_FROM_TYPE
          |         |--PRO_E_EXT_DEPTH_FROM_VALUE
          |         |--PRO_E_EXT_DEPTH_FROM_REF

*/ 

	ProTKPrintf(" PRO_E_HOLE_STD_DEPTH \n");
	ProTKPrintf(" ****************** \n");

	status = ProElementAlloc ( PRO_E_HOLE_STD_DEPTH, &elem_hole_std_depth );
	UG_HOLE_LOG (" ProElementAlloc PRO_E_HOLE_STD_DEPTH ", status);

	status = ProElemtreeElementAdd ( elem_hle_com, NULL, elem_hole_std_depth );
	UG_HOLE_LOG (" ProElemtreeElementAdd ", status);

	ProTKPrintf(" PRO_E_HOLE_DEPTH_TO \n", status);
	ProTKPrintf(" ****************** \n");

	status = ProElementAlloc ( PRO_E_HOLE_DEPTH_TO, &elem_hole_depth_to );
	UG_HOLE_LOG (" ProElementAlloc PRO_E_HOLE_DEPTH_TO ", status);

	status = ProElemtreeElementAdd ( elem_hole_std_depth, NULL, elem_hole_depth_to );
	UG_HOLE_LOG (" ProElemtreeElementAdd ", status);


	ProTKPrintf(" PRO_E_HOLE_DEPTH_TO_TYPE \n");
	ProTKPrintf(" ****************** \n");

	status = ProElementAlloc ( PRO_E_HOLE_DEPTH_TO_TYPE, &elem_hole_depth_to_type );
	UG_HOLE_LOG (" ProElementAlloc PRO_E_HOLE_DEPTH_TO_TYPE ", status);

	status = ProElementIntegerSet ( elem_hole_depth_to_type, PRO_HLE_STRGHT_THRU_ALL_DEPTH);
	UG_HOLE_LOG (" ProElementIntegerSet ", status ); 

	status = ProElemtreeElementAdd ( elem_hole_depth_to, NULL, elem_hole_depth_to_type );
    UG_HOLE_LOG (" ProElemtreeElementAdd ", status);


	ProTKPrintf(" PRO_E_HOLE_DEPTH_FROM \n");
	ProTKPrintf(" ****************** \n");

	status = ProElementAlloc ( PRO_E_HOLE_DEPTH_FROM, &elem_hole_depth_from );
	UG_HOLE_LOG (" ProElementAlloc PRO_E_HOLE_DEPTH_FROM ", status);

	status = ProElemtreeElementAdd ( elem_hole_std_depth, NULL, elem_hole_depth_from );
	UG_HOLE_LOG (" ProElemtreeElementAdd ", status);


	ProTKPrintf(" PRO_E_HOLE_DEPTH_FROM_TYPE \n");
	ProTKPrintf(" ****************** \n");

	status = ProElementAlloc ( PRO_E_HOLE_DEPTH_FROM_TYPE, &elem_hole_depth_from_type );
	UG_HOLE_LOG (" ProElementAlloc PRO_E_HOLE_DEPTH_FROM_TYPE ", status);

	status = ProElementIntegerSet ( elem_hole_depth_from_type, PRO_HLE_STRGHT_NONE_DEPTH);
	UG_HOLE_LOG (" ProElementIntegerSet ", status ); 

	status = ProElemtreeElementAdd ( elem_hole_depth_from, NULL, elem_hole_depth_from_type );
    UG_HOLE_LOG (" ProElemtreeElementAdd ", status);


/* Adding elements related with the placement details 

     |--PRO_E_HLE_PLACEMENT
     |    |--PRO_E_HLE_PRIM_REF
     |    |--PRO_E_HLE_PL_TYPE
     |    |--PRO_E_HLE_DIM_REF1
     |    |--PRO_E_HLE_DIM_DIST1
     |    |--PRO_E_HLE_DIM_REF2
     |    |--PRO_E_HLE_DIM_DIST2
	
*/ 

        ProTKPrintf(" PRO_E_HLE_PLACEMENT \n");
        ProTKPrintf(" ****************** \n");

        status = ProElementAlloc ( PRO_E_HLE_PLACEMENT, &elem_hle_placement );
        UG_HOLE_LOG (" ProElementAlloc PRO_E_HLE_PLACEMENT", status);

        status = ProElemtreeElementAdd ( feat_elemtree, NULL, elem_hle_placement );
        UG_HOLE_LOG (" ProElemtreeElementAdd ", status);


	ProTKPrintf(" PRO_E_HLE_PRIM_REF \n");
	ProTKPrintf(" ****************** \n");

	status = ProElementAlloc ( PRO_E_HLE_PRIM_REF, &elem_hle_prim_ref );
	UG_HOLE_LOG (" ProElementAlloc PRO_E_HLE_PRIM_REF ", status);

	ProTKPrintf("Select a surface for Hole Placement \n");
	status = ProSelect ( "datum,surface", 1, NULL, NULL, NULL, NULL,
			     &p_selection, &n_selection);
	if ( n_selection <= 0 ) return (0);
	UG_HOLE_LOG (" ProSelect ", status);

	status = ProSelectionToReference( p_selection[0], &reference );
    UG_HOLE_LOG (" ProSelectionToReference ", status);

	status = ProElementReferenceSet( elem_hle_prim_ref, reference );
     UG_HOLE_LOG("ProElementReferenceSet", status );

	status = ProElemtreeElementAdd( elem_hle_placement, NULL, elem_hle_prim_ref );
	UG_HOLE_LOG( "ProElemtreeElementAdd", status );

	ProTKPrintf(" PRO_E_HLE_PL_TYPE \n");
	ProTKPrintf(" ****************** \n");

	status = ProElementAlloc ( PRO_E_HLE_PL_TYPE, &elem_hle_pl_type );

	status = ProElementIntegerSet ( elem_hle_pl_type, PRO_HLE_PL_TYPE_LIN);
	UG_HOLE_LOG (" ProElementIntegerSet ", status ); 

	status = ProElemtreeElementAdd ( elem_hle_placement, NULL, elem_hle_pl_type );
    UG_HOLE_LOG (" ProElemtreeElementAdd ", status);

	ProTKPrintf(" PRO_E_HLE_DIM_REF1 \n");
	ProTKPrintf(" ****************** \n");

	status = ProElementAlloc ( PRO_E_HLE_DIM_REF1, &elem_hle_dim_ref1 );
	UG_HOLE_LOG (" ProElementAlloc PRO_E_HLE_DIM_REF1 ", status);

	ProTKPrintf("Select a 1st Reference for Hole Placement \n");
	status = ProSelect ( "datum,surface,edge", 1, NULL, NULL, NULL, NULL,
			     &p_selection, &n_selection);
	if ( n_selection <= 0 ) return (0);
	UG_HOLE_LOG (" ProSelect ", status);

	status = ProSelectionToReference( p_selection[0], &reference );
    UG_HOLE_LOG (" ProSelectionToReference ", status);

	status = ProElementReferenceSet( elem_hle_dim_ref1, reference );
     UG_HOLE_LOG("ProElementReferenceSet", status );

	status = ProElemtreeElementAdd( elem_hle_placement, NULL, elem_hle_dim_ref1 );
	UG_HOLE_LOG( "ProElemtreeElementAdd", status );

	ProTKPrintf(" PRO_E_HLE_DIM_DIST1 \n");
	ProTKPrintf(" ****************** \n");

	status = ProElementAlloc ( PRO_E_HLE_DIM_DIST1, &elem_hle_dim_dist1 );
	UG_HOLE_LOG (" ProElementAlloc PRO_E_HLE_DIM_DIST1 ", status);

	status = ProElementDoubleSet ( elem_hle_dim_dist1, (double) 100.0);
	UG_HOLE_LOG (" ProElementDoubleSet ", status ); 

	status = ProElemtreeElementAdd ( elem_hle_placement, NULL, elem_hle_dim_dist1 );
    UG_HOLE_LOG (" ProElemtreeElementAdd ", status);

	ProTKPrintf(" PRO_E_HLE_DIM_REF2 \n");
	ProTKPrintf(" ****************** \n");

	status = ProElementAlloc ( PRO_E_HLE_DIM_REF2, &elem_hle_dim_ref2 );
	UG_HOLE_LOG (" ProElementAlloc PRO_E_HLE_DIM_REF2 ", status);

	ProTKPrintf("Select a 2st Reference for Hole Placement \n");
	status = ProSelect ( "datum,surface,edge", 1, NULL, NULL, NULL, NULL,
			     &p_selection, &n_selection);
	if ( n_selection <= 0 ) return (0);
	UG_HOLE_LOG (" ProSelect ", status);

	status = ProSelectionToReference( p_selection[0], &reference );
    UG_HOLE_LOG (" ProSelectionToReference ", status);

	status = ProElementReferenceSet( elem_hle_dim_ref2, reference );
    UG_HOLE_LOG("ProElementReferenceSet", status );

	status = ProElemtreeElementAdd( elem_hle_placement, NULL, elem_hle_dim_ref2 );
	UG_HOLE_LOG( "ProElemtreeElementAdd", status );

	ProTKPrintf(" PRO_E_HLE_DIM_DIST2 \n");
	ProTKPrintf(" ****************** \n");

	status = ProElementAlloc ( PRO_E_HLE_DIM_DIST2, &elem_hle_dim_dist2 );
	UG_HOLE_LOG (" ProElementAlloc PRO_E_HLE_DIM_DIST2 ", status);

	status = ProElementDoubleSet ( elem_hle_dim_dist2, (double) 200.0);
	UG_HOLE_LOG (" ProElementDoubleSet ", status ); 

	status = ProElemtreeElementAdd ( elem_hle_placement, NULL, elem_hle_dim_dist2 );
    UG_HOLE_LOG (" ProElemtreeElementAdd ", status);
/* End of Element Tree Creation */ 


/* Start of Feature Creation */ 

	status = ProMdlCurrentGet ( &model ); 
	UG_HOLE_LOG (" ProMdlCurrentGet ", status);

	status = ProMdlToModelitem( model, &model_item );
	UG_HOLE_LOG (" ProMdlToModelitem ", status);

	status = ProSelectionAlloc( NULL, &model_item, &model_selection );
	UG_HOLE_LOG (" ProSelectionAlloc ", status);

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

	options[0]= PRO_FEAT_CR_DEFINE_MISS_ELEMS;

	status = ProFeatureWithoptionsCreate ( model_selection, feat_elemtree,
		options, PRO_REGEN_NO_FLAGS, &created_feature, &p_errors );

	UG_HOLE_LOG (" ProFeatureWithoptionsCreate ", status);

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

/* End of Feature Creation */ 
		

/* Freeing the resources */ 

	status = ProElementFree( &feat_elemtree ); 
	UG_HOLE_LOG (" ProElementFree ", status);

	status = ProSelectionFree( &model_selection ); 
	UG_HOLE_LOG (" ProSelectionFree ", status);

/* End of Freeing */ 
	
        return ( status );
}

/*===============================================================*\
FUNCTION : UserElemtreeElementAdd
PURPOSE  : Adding an element to the parent element / tree 
input   : parent_element, child_element, value_data 
output  : none 
returns : 
	PRO_TK_NO_ERROR - Successfully added the element 
	PRO_TK_GENERAL_ERROR - Failed to add the element 
	any other return as returned by ProElemtreeElementAdd()
\*===============================================================*/