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

#include <ProToolkit.h>
#include <ProMfg.h>
#include <ProSolid.h>
#include <ProSelection.h>
#include <ProAsmcomppath.h>
#include <ProElement.h>
#include <ProElemId.h>
#include <ProValue.h>
#include <ProFeature.h>
#include <ProUtil.h>
#include <ProWcell.h>
#include <ProUtil.h>
#include <ProModelitem.h>
#include <ProMfgOptions.h>
#include <ProFeatType.h>
#include <ProToolinput.h>
#include <ProMdlUnits.h>
#include <ProTool.h>
#include <ProTKRunTime.h>

#include <TestError.h>
#include <UtilString.h>
#include <UtilTree.h>
#include <TestConsts.h>
#include <UgMfg.h>


/*====================================================================*\
FUNCTION : UserMfgWcellInitTools
PURPOSE  : Create tools and add to tool table
\*====================================================================*/
static ProError UserMfgWcellInitTools( ProMfg         mfg_model,
                                       ProElement     tool_arr_elem  )
{
 ProTool		tool;
 ProError		err = PRO_TK_NO_ERROR;
 static MfgPrmDblValue  drill_params[] =
 {
   { "CUTTER_DIAM",         12.0   },
   { "LENGTH",              80.0   },
   { "POINT_ANGLE",         118.0  }
 };
 static MfgPrmDblValue  center_drill_params[] =
 {
   { "CUTTER_DIAM",         13.0  },
   { "POINT_ANGLE",         118.0 },
   { "LENGTH",              50.0  },
   { "CSINK_ANGLE",         90.0  },
   { "DRILL_DIAMETER",      5.0   },
   { "DRILL_LENGTH",        5.0   },
 };
 static MfgPrmDblValue  end_mill_params[] =
 {
   { "CUTTER_DIAM",         20.0 },
   { "LENGTH",              60.0 }
 };
 int			n_params= 0;
 int			pocket_num;
 ProPath		tool_file;


 /*-----------------------------------------------*/
 /* Add drill                                     */
 /*-----------------------------------------------*/
 pocket_num = 1;

 n_params = sizeof( drill_params )/sizeof( MfgPrmDblValue );
 err = UserParamToolCreate( mfg_model, PRO_TOOL_DRILL, L"DRILL_D12",
                            drill_params, n_params, PRO_UNITLENGTH_MM,
                            &tool );
 ERROR_CHECK( "UserMfgWcellInitTools", "UserParamToolCreate", err );

 err = UserMfgWcellAddToolSetup( &tool, pocket_num, tool_arr_elem );
 ERROR_CHECK( "UserMfgWcellInitTools", "UserMfgWcellAddToolSetup", err );

 /*-----------------------------------------------*/
 /* Add center-drill                              */
 /*-----------------------------------------------*/
 pocket_num = 2;

 n_params = sizeof( center_drill_params )/sizeof( MfgPrmDblValue );
 err = UserParamToolCreate( mfg_model, PRO_TOOL_CENTER_DRL, L"C-DRILL_D12",
                            center_drill_params, n_params, PRO_UNITLENGTH_MM,
                            &tool );
 ERROR_CHECK( "UserMfgWcellInitTools", "UserParamToolCreate", err );

 err = UserMfgWcellAddToolSetup( &tool, pocket_num, tool_arr_elem );
 ERROR_CHECK( "UserMfgWcellInitTools", "UserMfgWcellAddToolSetup", err );

 /*-----------------------------------------------*/
 /* Add end mill                                  */
 /*-----------------------------------------------*/
 pocket_num = 3;

 n_params = sizeof( end_mill_params )/sizeof( MfgPrmDblValue );
 err = UserParamToolCreate( mfg_model, PRO_TOOL_END_MILL, L"END_MILL_D20",
                            end_mill_params, n_params, PRO_UNITLENGTH_MM,
                            &tool );
 ERROR_CHECK( "UserMfgWcellInitTools", "UserParamToolCreate", err );

 err = UserMfgWcellAddToolSetup( &tool, pocket_num, tool_arr_elem );
 ERROR_CHECK( "UserMfgWcellInitTools", "UserMfgWcellAddToolSetup", err );

 /*-----------------------------------------------*/
 /* Add drill by reading a file                   */
 /*-----------------------------------------------*/
 pocket_num = 4;
 
 ProStringToWstring ( tool_file, "mill_d20.xml");

 err = UserToolFileRead( mfg_model, L"MILL_D20", tool_file, PRO_B_TRUE, 
                         &tool );

 ERROR_CHECK( "UserMfgWcellInitTools", "UserToolFileRead", err );

 err = UserMfgWcellAddToolSetup( &tool, pocket_num, tool_arr_elem );
 ERROR_CHECK( "UserMfgWcellInitTools", "UserMfgWcellAddToolSetup", err );

 return ( err );
}

/*====================================================================*\
Function : UserToolHeadSet()
Purpose  : Setup a tool table
\*====================================================================*/
static ProError UserToolHeadSet( ProElement head_elem )
{
 ProError	err = PRO_TK_NO_ERROR;
 ProMfg		mfg_model;
 ProElement	tool_arr_elem;

 err = ProMdlCurrentGet( (ProMdl*)&mfg_model );
 ERROR_CHECK( "UserToolHeadSet","ProMdlCurrentGet", err );

 err = ProElementAlloc( PRO_E_MFG_WCELL_TOOL_SETUP_ARR, &tool_arr_elem );
 ERROR_CHECK( "UserToolHeadSet", "ProElementAlloc", err );

 err = UserMfgWcellInitTools( mfg_model, tool_arr_elem );
 ERROR_CHECK( "UserToolHeadSet","UserMfgWcellInitTools",err );

 err = ProElemtreeElementAdd( head_elem, NULL, tool_arr_elem );
 ERROR_CHECK( "UserToolHeadSet","ProElemtreeElementAdd",err );

 return ( err );
}

/*====================================================================*\
FUNCTION : UserWorkcellCreate
PURPOSE  : Create a workcell
\*====================================================================*/
int UserWorkcellCreate ()
{
 ProMdl			mfg_model;
 ProElement		element = NULL;      /* Individual element */
 ProElement		elem_tree = NULL; /* Entire tree        */
 ProValueData		value_data;
 ProValue		value;
 ProFeature		wc_feature;
 ProError		err = PRO_TK_NO_ERROR;
 int                    n_dbl_params = 0;
 int                    n_str_params = 0;
 int			ii = 0, num_elems = 0;
 static ElemTable	elem_table[] = 
 {
   { PRO_E_FEATURE_TYPE,        PRO_VALUE_TYPE_INT     },
   { PRO_E_WCELL_TYPE,          PRO_VALUE_TYPE_INT     },
   { PRO_E_STD_FEATURE_NAME,    PRO_VALUE_TYPE_WSTRING },
   { PRO_E_MFG_WCELL_NUM_AXES,  PRO_VALUE_TYPE_INT     },
   { PRO_E_MFG_PARAM_ARR,       ARRAY                  },
   { PRO_E_MFG_WCELL_HEAD_1,    COMPOUND               },
   { PRO_E_MFG_COMMENTS,        PRO_VALUE_TYPE_WSTRING }
 };
 static MfgPrmDblValue  dbl_params[] =  /* example (not required) */
 {
   { "RAPID_FEED_RATE",    500.0    }
 };
 static MfgPrmStrValue  str_params[] =  /* examples (not required) */
 {
   { "MACH_NAME",              L"GPOST348"         },
   { "MACH_ID",                L"5"                },
   { "CONTROLLER",             L"FANUC 6M"         },
   { "LOADTL_OUTPUT",          L"MODAL_OUTPUT"     },
   { "SPINDL_OFF_OUTPUT",      L"NO"               },
   { "COOLNT_OFF_OUTPUT",      L"NO"               },
   { "CUTCOM_GEOMETRY_TYPE",   L"OUTPUT_ON_CENTER" }
 };


 n_dbl_params = sizeof( dbl_params ) / sizeof( MfgPrmDblValue );
 n_str_params = sizeof( str_params ) / sizeof( MfgPrmStrValue );
/*
*/

 num_elems = sizeof( elem_table ) / sizeof( ElemTable );
   
 err = ProElementAlloc( PRO_E_FEATURE_TREE, &elem_tree );
 ERROR_CHECK( "UserWorkcellCreate","ProElementAlloc()", err );
    
 for ( ii = 0 ; ii < num_elems; ii++ )
 {
   err = ProElementAlloc( elem_table[ii].elem_type, &element );
   ERROR_CHECK( "UserWorkcellCreate","ProElementAlloc()", err );

   switch ( elem_table[ii].elem_type )
   {
     case PRO_E_FEATURE_TYPE:
	value_data.v.i = PRO_FEAT_WORKCELL;
	break;

     case PRO_E_WCELL_TYPE:
	value_data.v.i = PRO_WCELL_MILL;
	break;

     case PRO_E_MFG_WCELL_NUM_AXES:
	value_data.v.i = PRO_WCELL_3_AXIS;
	break;

     case PRO_E_MFG_PARAM_ARR:
        if ( n_dbl_params != 0 || n_str_params != 0 )
        {
          err = UserMfgParamArrSet( dbl_params, n_dbl_params,
                                    str_params, n_str_params,
                                    element );
          ERROR_CHECK( "UserWorkcellCreate", "UserMfgParamArrSet()", err );
        }
        else
        {
          err = ProElementFree( &element );
          continue;
        }
        break;

     case PRO_E_STD_FEATURE_NAME:
	 value_data.v.w = (wchar_t*) malloc( sizeof( ProName ) );
	if ( value_data.v.w != NULL )
	   ProStringToWstring( value_data.v.w, "Mill_3_Axis" );
	break;

     case PRO_E_MFG_COMMENTS:
       value_data.v.w = (wchar_t*) malloc( sizeof(ProComment) );
	if ( value_data.v.w != NULL )
	   ProStringToWstring( value_data.v.w, "Just example" );
	break;

     case PRO_E_MFG_WCELL_HEAD_1:
	err = UserToolHeadSet( element );
	break;

     default:
	ProTKFprintf( stderr, "Error setting element type\n" );
	err = PRO_TK_GENERAL_ERROR;
        ERROR_CHECK( "UserWorkcellCreate", "UserWorkcellCreate()", err );
	break;
   }

   if ( elem_table[ii].val_type == PRO_VALUE_TYPE_INT)
   	{
		err = ProElementIntegerSet (element, value_data.v.i);
		ERROR_CHECK( "UserWorkcellCreate","ProElementIntegerSet()", err );
   	}
   else if (elem_table[ii].val_type == PRO_VALUE_TYPE_WSTRING )
   {
		err = ProElementWstringSet(element, value_data.v.w);
		ERROR_CHECK( "UserWorkcellCreate", "ProElementWstringSet()", err );
   }

  	err = ProElemtreeElementAdd( elem_tree, NULL, element );
   	ERROR_CHECK( "UserWorkcellCreate", "ProElemtreeElementAdd()", err );
 }

 ProUtilElementtreePrint( elem_tree, PRO_TEST_INFO_WINDOW, NULL );

 err = ProMdlCurrentGet( &mfg_model );
 ERROR_CHECK( "UserWorkcellCreate","ProMdlCurrentGet", err );

 /*********************************************/
 /* Create feature                            */
 /*********************************************/
 err = UserMfgModelFeatureCreate( mfg_model, elem_tree, &wc_feature );
 ERROR_CHECK( "UserWorkcellCreate", "UserMfgModelFeatureCreate()", err );

 err = ProElementFree( &elem_tree );
 ERROR_CHECK( "UserWorkcellCreate", "ProElementFree()", err );

 return( (int)err );
}

/*====================================================================*\
Function : UserWpieceSelCreate()
Purpose  : Create a selection handle for the mfg assembly or items in it
\*====================================================================*/
ProError UserWpieceSelCreate (
/*--------------------------------------------------------------------*/
ProMfg		mfg_model,
int		item_id,
ProType		item_type,
ProSelection	*selection

)
/*--------------------------------------------------------------------*/
{
 ProSolid	mfg_solid;
 ProAsmcomppath	comp_path;
 ProModelitem	wkpiece_item;
 ProError	err = PRO_TK_NO_ERROR;

 err = ProMfgSolidGet( mfg_model, &mfg_solid );
 ERROR_CHECK( "UserWpieceSelCreate", "ProMfgSolidGet()", err );

 if ( err == PRO_TK_NO_ERROR )
 {
   err= ProMfgFeatureOwnerGet( mfg_model, &comp_path );
   ERROR_CHECK( "UserWpieceSelCreate", "ProMfgSolidGet()", err );
 }

 if ( err == PRO_TK_NO_ERROR )
 {
   err = ProModelitemInit( mfg_solid, item_id, item_type, &wkpiece_item );
   ERROR_CHECK( "UserWpieceSelCreate", "ProModelitemInit()", err );
 }

 if ( err == PRO_TK_NO_ERROR )
 {
   err = ProSelectionAlloc( &comp_path, &wkpiece_item, selection );
   ERROR_CHECK( "UserWpieceSelCreate", "ProSelectionAlloc()", err );
 }

 return ( err );
}

/*====================================================================*\
FUNCTION : UserToolSetupSet
PURPOSE  : Create tools and add to tool table
\*====================================================================*/
ProError UserToolSetupSet( 
/*--------------------------------------------------------------------*/
ProTool		*tool,
int		pocket_num,
ProElement	tool_setup_elem

)
/*--------------------------------------------------------------------*/
{
 ProError		err = PRO_TK_NO_ERROR;
 ProElement		element = NULL;
 ProValueData		value_data;
 ProValue		value;
 int			ii = 0, table_size = 0;
 static ElemTable	tsetup_elem_table[] = 
 {
   { PRO_E_MFG_WCELL_TOOL_POCKET_NUM, PRO_VALUE_TYPE_INT     },
   { PRO_E_MFG_WCELL_TOOL_ID,         PRO_VALUE_TYPE_WSTRING }
 };

 table_size = sizeof( tsetup_elem_table ) / sizeof( ElemTable );

 for ( ii = 0; ii < table_size; ii++ )
 {
   err = ProElementAlloc( tsetup_elem_table[ii].elem_type, &element );
   ERROR_CHECK( "UserToolSetupSet","ProElementAlloc()", err );

   switch ( tsetup_elem_table[ii].elem_type )
   {
     case PRO_E_MFG_WCELL_TOOL_POCKET_NUM:
        value_data.v.i = pocket_num;
		err = ProElementIntegerSet (element, value_data.v.i);
        break;

     case PRO_E_MFG_WCELL_TOOL_ID:
        value_data.v.w = (wchar_t*) malloc( sizeof( ProName ) );
        if ( value_data.v.w != NULL )
        {
          err = ProWstringCopy( tool->tool_id, value_data.v.w, 
                                PRO_VALUE_UNUSED );
          ERROR_CHECK( "UserToolSetupSet","ProWstringCopy()", err );
        }
		err = ProElementWstringSet(element,  value_data.v.w);
		ERROR_CHECK( "UserToolSetupSet","ProElementWstringSet()", err );
        break;

     default:
        ProTKFprintf( stderr, "Error setting element type\n" );
        err = PRO_TK_GENERAL_ERROR;
        ERROR_CHECK( "UserToolSetupSet","UserToolSetupSet()", err );
        break;
   }

   err = ProElemtreeElementAdd( tool_setup_elem, NULL, element );
   ERROR_CHECK( "UserToolSetupSet","ProElemtreeElementAdd", err );
 }

 return ( err );
}

/*====================================================================*\
FUNCTION : UserMfgWcellAddToolSetup
PURPOSE  : Adds tool setup element
\*====================================================================*/
ProError UserMfgWcellAddToolSetup( ProTool	*tool,
                                   int		pocket_num,
                                   ProElement	tool_arr_elem )
                                  
{
 ProError	err = PRO_TK_NO_ERROR;
 ProElement	tool_setup_elem = NULL;

 err = ProElementAlloc( PRO_E_MFG_WCELL_TOOL_SETUP, &tool_setup_elem );
 ERROR_CHECK( "UserMfgWcellAddToolSetup", "ProElementAlloc", err );

 err = UserToolSetupSet( tool, pocket_num, tool_setup_elem );
 ERROR_CHECK( "UserMfgWcellAddToolSetup", "UserToolSetupSet", err );

 err = ProElemtreeElementAdd( tool_arr_elem, NULL, tool_setup_elem );
 ERROR_CHECK( "UserMfgWcellAddToolSetup","ProElemtreeElementAdd", err );

 return ( err );
}

/*====================================================================*\
FUNCTION : UserWorkcellTreeToolPocketGet
PURPOSE  : Finds pocket by tool id (first found)
\*====================================================================*/
ProBool UserWorkcellTreeToolPocketGet( 
/*--------------------------------------------------------------------*/
ProElement		wc_elem_tree,
ProMfgToolHeadType	head_num,
ProLine			tool_name,
int			*p_pocket_num

)
/*--------------------------------------------------------------------*/
{
 ProError		err = PRO_TK_NO_ERROR;
 ProElement		elem_tree;
 ProElempath		path;
 ProElempath		id_path;
 ProElempath		pocket_path;
 ProElement		tool_arr_elem;
 ProElement		*tool_setups;
 ProElement		tool_id_elem;
 ProElement		pocket_elem;
 ProLine		tool_name_upper;
 ProValue		value;
 wchar_t		*tool_id = NULL;
 int			tool_arr_path_size;
 int			pocket_num = 1;
 int			result;
 int			ii, num;
 ProBool		found = PRO_B_FALSE;
 ProElempathItem	p_items[3];
 ProElempathItem        tooling_path_items[2] =
 {
   { PRO_ELEM_PATH_ITEM_TYPE_ID, PRO_E_MFG_WCELL_HEAD_1         },
   { PRO_ELEM_PATH_ITEM_TYPE_ID, PRO_E_MFG_WCELL_TOOL_SETUP_ARR }
 };

 tool_arr_path_size = sizeof( tooling_path_items )/sizeof( ProElempathItem );

 /*-------------------------------------------------------*\
    Get element PRO_E_MFG_WCELL_TOOL_SETUP_ARR
 \*-------------------------------------------------------*/
 if ( head_num == PRO_MFG_TOOL_HEAD_2 )
   tooling_path_items[0].path_item.elem_id = PRO_E_MFG_WCELL_HEAD_2;

 ProElempathAlloc( &path );
 ProElempathDataSet( path, tooling_path_items, tool_arr_path_size );

 ProArrayAlloc( 0, sizeof(ProElement), 4, (ProArray *)&tool_setups );

 err = ProElementChildrenGet( wc_elem_tree, path, &tool_setups );
 ERROR_CHECK( "UserWorkcellTreeToolPocketGet", "ProElementChildrenGet", err );

 ProElempathFree( &path );

 ProArraySizeGet( (ProArray)tool_setups, &num );

 ProElempathAlloc( &pocket_path );
 p_items[0].type = PRO_ELEM_PATH_ITEM_TYPE_ID;
 p_items[0].path_item.elem_id = PRO_E_MFG_WCELL_TOOL_POCKET_NUM ;
 ProElempathDataSet( pocket_path, p_items, 1 );

 ProElempathAlloc( &id_path );
 p_items[0].type = PRO_ELEM_PATH_ITEM_TYPE_ID;
 p_items[0].path_item.elem_id = PRO_E_MFG_WCELL_TOOL_ID ;
 ProElempathDataSet( id_path, p_items, 1 );

 for ( ii = 0; ii < num; ii++ )
 {
   /*-------------------------------------------------------*\
      Get element PRO_E_MFG_WCELL_TOOL_ID
   \*-------------------------------------------------------*/
   err = ProElemtreeElementGet( tool_setups[ii], id_path, &tool_id_elem );
   ERROR_CHECK( "UserWorkcellTreeToolPocketGet", "ProElemtreeElementGet", 
                err );

   err = ProElementWstringGet( tool_id_elem, NULL, &tool_id );
   ERROR_CHECK( "UserWorkcellTreeToolPocketGet", "ProElementWstringGet", err );

   err = ProWstringCompare( tool_name, tool_id, PRO_VALUE_UNUSED, &result );
   ERROR_CHECK( "UserWorkcellTreeToolPocketGet", "ProWstringCompare", err );

   ProWstringFree( tool_id );

   if ( result == 0 )
   {
     err = ProElemtreeElementGet( tool_setups[ii], pocket_path, 
                                  &pocket_elem );
     ERROR_CHECK( "UserWorkcellTreeToolPocketGet", "ProElemtreeElementGet", 
                  err );

     err = ProElementIntegerGet( pocket_elem, NULL, &pocket_num );
     ERROR_CHECK( "UserWorkcellTreeToolPocketGet", "ProElementIntegerGet", 
                  err );

     found = PRO_B_TRUE;
     break;
   }
 }

 if ( p_pocket_num != NULL )
   *p_pocket_num = pocket_num;

 ProElempathFree( &id_path );
 ProElempathFree( &pocket_path );
 ProArrayFree( (ProArray *)&tool_setups );

 return ( found );
}

/*====================================================================*\
FUNCTION : UserWorkcellToolAdd
PURPOSE  : Add flat mill cutter to workcell tooling
\*====================================================================*/
ProError UserWorkcellToolAdd( 
/*--------------------------------------------------------------------*/
ProMfg			mfg_model,
ProSelection		workcell,
ProMfgToolHeadType	head_num,
ProToolType		tool_type,
ProLine			tool_name,
MfgPrmDblValue		params[],
int			n_params,
ProUnitLength		units,
ProBool			allow_reuse_existing,
int			*p_pocket_num

)
/*--------------------------------------------------------------------*/
{
 ProError		err = PRO_TK_NO_ERROR;
 ProErrorlist		errors;
 ProElement		elem_tree;
 ProFeature		wcell_feat;
 ProTool		tool;
 ProElempath		path;
 ProElement		tool_arr_elem;
 ProElement		tool_setup_elem;
 ProBool		found = PRO_B_FALSE;
 int			path_size;
 int			pocket_num = 1;
 ProElempathItem        tooling_path_items[2] =
 {
   { PRO_ELEM_PATH_ITEM_TYPE_ID, PRO_E_MFG_WCELL_HEAD_1         },
   { PRO_ELEM_PATH_ITEM_TYPE_ID, PRO_E_MFG_WCELL_TOOL_SETUP_ARR }
 };
 ProFeatureCreateOptions opts[] = {PRO_FEAT_CR_NO_OPTS};


 path_size = sizeof( tooling_path_items ) / sizeof( ProElempathItem );

 err = ProToolInit( tool_name, mfg_model, &tool );
 ERROR_CHECK( "UserWorkcellToolAdd", "ProToolInit", err );

 /*-------------------------------------------------------*\
    Verify that tool doesn't exist in mfg model
 \*-------------------------------------------------------*/
 err = ProToolVerify( &tool );

 if ( err == PRO_TK_E_NOT_FOUND )
 {
   /*-------------------------------------------------------*\
      Add tool to mfg model if it doesn't exist 
   \*-------------------------------------------------------*/
   err = UserParamToolCreate( mfg_model, tool_type, tool_name, 
                              params, n_params, units, &tool );
   ERROR_CHECK( "UserWorkcellToolAdd", "UserParamToolCreate", err );
 }

 /*-------------------------------------------------------*\
    Extract workcell elem tree to modify (to add new tool)
 \*-------------------------------------------------------*/
 err = ProSelectionModelitemGet( workcell, &wcell_feat );
 ERROR_CHECK( "UserWorkcellToolAdd", "ProSelectionModelitemGet", err );

 err = ProFeatureElemtreeExtract( &wcell_feat, NULL, 
                                  PRO_FEAT_EXTRACT_NO_OPTS, 
                                  &elem_tree );
 ERROR_CHECK( "UserWorkcellToolAdd", "ProFeatureElemtreeExtract", err );

 /*-------------------------------------------------------*\
    Pocket number 
 \*-------------------------------------------------------*/
 if ( allow_reuse_existing )
 {
   found = UserWorkcellTreeToolPocketGet( elem_tree, head_num, tool_name,
                                          &pocket_num );
   if ( found )
   {
     if ( p_pocket_num != NULL )
       *p_pocket_num = pocket_num;

     return ( PRO_TK_NO_ERROR );
   }
 }

 err = ProWcellMaxToolPosGet( &wcell_feat, head_num, &pocket_num );
 ERROR_CHECK( "UserWorkcellToolAdd", "ProWcellMaxToolPosGet", err );

 pocket_num++;

 /*-------------------------------------------------------*\
    Get element PRO_E_MFG_WCELL_TOOL_SETUP_ARR
 \*-------------------------------------------------------*/
 if ( head_num == PRO_MFG_TOOL_HEAD_2 )
   tooling_path_items[0].path_item.elem_id = PRO_E_MFG_WCELL_HEAD_2;

 ProElempathAlloc( &path );
 ProElempathDataSet( path, tooling_path_items, path_size );

 err = ProElemtreeElementGet( elem_tree, path, &tool_arr_elem );
 ERROR_CHECK( "UserWorkcellToolAdd", "ProElemtreeElementGet", err );

 ProElempathFree( &path );

 /*-------------------------------------------------------*\
    Add tool setup 
 \*-------------------------------------------------------*/
 err = UserMfgWcellAddToolSetup( &tool, pocket_num, tool_arr_elem );
 ERROR_CHECK( "UserWorkcellToolAdd", "UserMfgWcellAddToolSetup", err );

 /*-------------------------------------------------------*\
    Redefined workcell feature
 \*-------------------------------------------------------*/
 err = ProFeatureRedefine( NULL, &wcell_feat, elem_tree, opts, 1, &errors );

 if ( err != PRO_TK_NO_ERROR )
   ProTKFprintf( stderr, "Error in element %d\n",
                 errors.error_list[0].err_item_id );

 ERROR_CHECK( "UserWorkcellToolAdd","ProFeatureRedefine", err );

 if ( tool_name != NULL )
   ProWstringCopy( tool.tool_id, tool_name, PRO_VALUE_UNUSED );

 if ( p_pocket_num != NULL )
   *p_pocket_num = pocket_num;

 return ( err );
}