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

static ProFileName message_file; 

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

/*---------------------- Function Prototypes -------------------------*/
int ProDemoBaseExtrudeProtrCreate();

/*------------------------- External Data ----------------------------*/
ProError ProDemoSectCreate();

/*------------------------- Global Data -----------------------------*/
typedef struct tree_element_data
{
  ProElement    tree;
  ProElement    parent_element;
  ProElemId     elem_id;
  ProValueData  value_data;
} ProTreeElemdata;

ProError ProTestFeatElemAdd (ProTreeElemdata *elem);

/*===============================================================*\
FUNCTION : ProDemoBaseExtrudeProtrCreate
PURPOSE  : Demonstrates the creation of the extruded protrusion
           base feature.
\*===============================================================*/
int ProDemoBaseExtrudeProtrCreate()
{
    ProTreeElemdata         elem;
    ProErrorlist            errors;
    ProMdl                  model;
    ProModelitem            model_item;
    ProSelection            model_sel;
    ProFeature              feature;
    ProFeatureCreateOptions *opts = NULL;
    ProElempath             path;
    ProElempathItem         path_items[2];
    ProSection              section;
    ProAsmcomppath          comp_path;
    ProAsmcomppath          *p_comp_path = NULL;
    ProElement              parent_elem;
    ProElement              parent_elem2;
    ProValue                value;
    double                  width;
    double                  height;
    double                  bite_radius;
    double                  bite_height;
    char                    name[PRO_NAME_SIZE];
    ProBoolean              alloc;
    ProError		    status;
    ProSelection * 	    sketch_selection;
    ProSelection * 	    selection_array;
    int 		    n_select; 

    ProStringToWstring ( message_file, "utilities.txt" ); 
/*---------------------------------------------------------------*\
    Allocate the element tree.
\*---------------------------------------------------------------*/
    status = ProElementAlloc (PRO_E_FEATURE_TREE, &(elem.tree));
    C_LOG(" ProElementAlloc"); 

/*---------------------------------------------------------------*\
    Add the feature type element to the tree.
\*---------------------------------------------------------------*/
    elem.parent_element = elem.tree;
    elem.elem_id = PRO_E_FEATURE_TYPE;
    elem.value_data.type = PRO_VALUE_TYPE_INT;
    elem.value_data.v.i = PRO_FEAT_PROTRUSION;
    status = ProTestFeatElemAdd (&elem);
    C_LOG(" ProTestFeatElemAdd"); 
	
/*---------------------------------------------------------------*\
    Add the feature form element to the tree.
\*---------------------------------------------------------------*/
    elem.parent_element = elem.tree;
    elem.elem_id = PRO_E_FEATURE_FORM; 
    elem.value_data.type = PRO_VALUE_TYPE_INT;
    elem.value_data.v.i = PRO_EXTRUDE;
    status = ProTestFeatElemAdd (&elem);
    C_LOG(" ProTestFeatElemAdd"); 

/*---------------------------------------------------------------*\
    Add the feature solid/surface/cut element to the tree.
\*---------------------------------------------------------------*/
    elem.parent_element = elem.tree;
    elem.elem_id = PRO_E_EXT_SURF_CUT_SOLID_TYPE; 
    elem.value_data.type = PRO_VALUE_TYPE_INT;
    elem.value_data.v.i = PRO_EXT_FEAT_TYPE_SOLID;
    status = ProTestFeatElemAdd (&elem);
    C_LOG(" ProTestFeatElemAdd"); 

/*---------------------------------------------------------------*\
    Add the feature addition/removal material element to the tree.
\*---------------------------------------------------------------*/
    elem.parent_element = elem.tree;
    elem.elem_id = PRO_E_REMOVE_MATERIAL; 
    elem.value_data.type = PRO_VALUE_TYPE_INT;
    elem.value_data.v.i = PRO_EXT_MATERIAL_ADD;
    status = ProTestFeatElemAdd (&elem);
    C_LOG(" ProTestFeatElemAdd"); 

/*---------------------------------------------------------------*\
    Add the feature thin element to the tree.
\*---------------------------------------------------------------*/
    elem.parent_element = elem.tree;
    elem.elem_id = PRO_E_FEAT_FORM_IS_THIN; 
    elem.value_data.type = PRO_VALUE_TYPE_INT;
    elem.value_data.v.i = PRO_EXT_FEAT_FORM_NO_THIN;
    status = ProTestFeatElemAdd (&elem);
    C_LOG(" ProTestFeatElemAdd"); 

/*---------------------------------------------------------------*\
    Add the standard section element to the tree.
\*---------------------------------------------------------------*/
    elem.parent_element = elem.tree;
    elem.elem_id = PRO_E_STD_SECTION;
    elem.value_data.type = -1;
    elem.value_data.v.i = -1;
    status = ProTestFeatElemAdd (&elem);
    C_LOG(" ProTestFeatElemAdd"); 

/*---------------------------------------------------------------*\
    Add the section depth elements to the element tree.
\*---------------------------------------------------------------*/
    elem.parent_element = elem.tree;
    elem.elem_id = PRO_E_STD_EXT_DEPTH;
    elem.value_data.type = -1;
    elem.value_data.v.i = -1;
    status = ProTestFeatElemAdd (&elem);
    C_LOG(" ProTestFeatElemAdd"); 
    parent_elem2 = elem.parent_element;

    elem.elem_id = PRO_E_EXT_DEPTH_FROM;
    elem.value_data.type = -1;
    elem.value_data.v.i = -1;
    status = ProTestFeatElemAdd (&elem);
    C_LOG(" ProTestFeatElemAdd"); 
    parent_elem = elem.parent_element;
    elem.elem_id = PRO_E_EXT_DEPTH_FROM_TYPE;
    elem.value_data.type = PRO_VALUE_TYPE_INT;
    elem.value_data.v.i = PRO_EXT_DEPTH_FROM_BLIND;
	status = ProTestFeatElemAdd (&elem);
    C_LOG(" ProTestFeatElemAdd"); 
    elem.parent_element = parent_elem;
    elem.elem_id = PRO_E_EXT_DEPTH_FROM_VALUE;
    elem.value_data.type = PRO_VALUE_TYPE_DOUBLE;
    elem.value_data.v.d = 50.0;
    status = ProTestFeatElemAdd (&elem);
    C_LOG(" ProTestFeatElemAdd"); 

    elem.parent_element = parent_elem2;
    elem.elem_id = PRO_E_EXT_DEPTH_TO;
    elem.value_data.type = -1;
    elem.value_data.v.i = -1;
    status = ProTestFeatElemAdd (&elem);
    C_LOG(" ProTestFeatElemAdd");
    parent_elem = elem.parent_element;
    elem.elem_id = PRO_E_EXT_DEPTH_TO_TYPE;
    elem.value_data.type = PRO_VALUE_TYPE_INT;
    elem.value_data.v.i = PRO_EXT_DEPTH_TO_BLIND;
    status = ProTestFeatElemAdd (&elem);
    C_LOG(" ProTestFeatElemAdd");
    elem.parent_element = parent_elem;
    elem.elem_id = PRO_E_EXT_DEPTH_TO_VALUE;
    elem.value_data.type = PRO_VALUE_TYPE_DOUBLE;
    elem.value_data.v.d = 0.0;
    status = ProTestFeatElemAdd (&elem);
    C_LOG(" ProTestFeatElemAdd");

    status = ProMdlCurrentGet (&model);
    C_LOG(" ProMdlCurrentGet"); 
    if ( status != PRO_TK_NO_ERROR ) return ( status );
    status = ProMdlToModelitem( model, &model_item ); 
    C_LOG(" ProMdlToModelitem"); 
    status = ProSelectionAlloc (p_comp_path, &model_item,
          &model_sel);
    C_LOG(" ProSelectionAlloc"); 

    status = ProMessageDisplay ( message_file, 
		"Select a Sketched Datum Curve Feature");
    C_LOG(" ProMessageDisplay"); 
    ProTKPrintf ( "Please Select a Sketched Datum Curve Feature \n");

    status = ProSelect ( "feature", 1, NULL, NULL, NULL, NULL, 
		      &sketch_selection, &n_select );
    C_LOG(" ProSelect"); 

    if ( n_select <= 0 ) return -1;

    status = ProArrayAlloc ( n_select, sizeof (ProSelection), 
                1, ( ProArray *)&selection_array ); 
    C_LOG(" ProArrayAlloc"); 

    status = ProSelectionCopy ( sketch_selection[0], &selection_array[0] ); 
    C_LOG(" ProSelectionCopy"); 

/*---------------------------------------------------------------*\
    Create the protrusion using the section of the selected feature
\*---------------------------------------------------------------*/
	status = ProArrayAlloc ( 1, sizeof (ProFeatureCreateOptions), 
		1, ( ProArray *)&opts ); 
	C_LOG(" ProArrayAlloc"); 
    
	opts[0] = PRO_FEAT_CR_DEFINE_MISS_ELEMS;
    status = ProFeatureSketchedWithOptionsCreate ( model_sel, elem.tree, 
                opts, selection_array, PRO_REGEN_NO_FLAGS,
                &feature, &errors );
    C_LOG(" ProFeatureSketchedWithOptionsCreate"); 

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

/*---------------------------------------------------------------*\
    Free up the allocated memory.
\*---------------------------------------------------------------*/
    status = ProElementFree (&elem.tree);
    C_LOG(" ProElementFree"); 

    return (status);
}

/*===============================================================*\
FUNCTION : ProTestFeatElemAdd
PURPOSE  : Adds a generic feature element to the element tree.
\*===============================================================*/
ProError ProTestFeatElemAdd (ProTreeElemdata *elem)
{
    ProElement  element;
    ProError    status;
     status = ProElementAlloc (elem->elem_id, &element);
    C_LOG(" ProElementAlloc"); 
	if(elem->value_data.type == PRO_VALUE_TYPE_INT)
	{
		status = ProElementIntegerSet (element, elem->value_data.v.i );
    	C_LOG( " ProElementIntegerSet" );
	}
	else if(elem->value_data.type == PRO_VALUE_TYPE_DOUBLE)
	{
		status = ProElementDoubleSet (element, elem->value_data.v.d );
    	C_LOG( " ProElementDoubleSet" );
	}
    status = ProElemtreeElementAdd (elem->parent_element, NULL, element);
    C_LOG(" ProElemtreeElementAdd"); 
    elem->parent_element = element;
    return (status);
}

#undef C_LOG
#undef C_PRINT