/*
	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 <ProMfgOptions.h>
#include <ProTKRunTime.h>

#include <TestError.h>
#include <UgMfg.h>

/*====================================================================*\
FUNCTION : UserHolesetStartSet
PURPOSE  : Add a holeset start element
\*====================================================================*/
ProError UserHolesetStartSet (
/*--------------------------------------------------------------------*/
ProDrillStartType	start_type,
ProSelection		sel_start,
ProElement		start_elem 

)
/*--------------------------------------------------------------------*/
{
 ProError		err = PRO_TK_NO_ERROR;
 ProValueData		value_data;
 ProValue		value = NULL;
 ProElement		elem;
 ProReference		reference;
 int			ii = 0, size = 0;
 static ElemTable	start_elem_table[] = 
 { 
   { PRO_E_HOLESET_START_TYPE,      PRO_VALUE_TYPE_INT       },
   { PRO_E_HOLESET_START_SURFACE,   PRO_VALUE_TYPE_SELECTION }
 };

 size = sizeof( start_elem_table )/ sizeof( ElemTable );

 for ( ii = 0 ; ii < size; ii++ )
 {
   if ( start_elem_table[ii].elem_type == PRO_E_HOLESET_START_SURFACE &&
        start_type == PRO_DRILL_AUTO_START )
   {
     continue;
   }

   err = ProElementAlloc( start_elem_table[ii].elem_type, &elem );
   ERROR_CHECK( "UserHolesetStartSet","ProElementAlloc()", err );

   switch ( start_elem_table[ii].elem_type )
   {
     case PRO_E_HOLESET_START_TYPE:
        value_data.v.i = start_type;
        break;

     case PRO_E_HOLESET_START_SURFACE:
        break;

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

   if ( start_elem_table[ii].val_type == PRO_VALUE_TYPE_INT )
   {
	 err = ProElementIntegerSet(elem,start_type );
     ERROR_CHECK( "UserHolesetStartSet", " ProElementIntegerSet()", err );
   }
   else if ( start_elem_table[ii].val_type == PRO_VALUE_TYPE_SELECTION )
   {
     err = ProSelectionToReference( sel_start, &reference );
     ERROR_CHECK( "UserHolesetStartSet()", "ProSelectionToReference", err );

     err = ProElementReferenceSet( elem, reference );
     ERROR_CHECK( "UserHolesetStartSet()", "ProElementReferenceSet", err );
   }

   err = ProElemtreeElementAdd( start_elem, NULL, elem );
   ERROR_CHECK( "UserHolesetStartSet", "ProElemtreeElementAdd()", err );
 }

 return ( err );
}

/*====================================================================*\
FUNCTION : UserHolesetEndSet
PURPOSE  : Add a holeset end to element
\*====================================================================*/
ProError UserHolesetEndSet (
/*--------------------------------------------------------------------*/
ProDrillEndType	end_type,
double 		depth,
ProElement	end_elem 

)
/*--------------------------------------------------------------------*/
{
 ProError		err = PRO_TK_NO_ERROR;
 ProValueData		value_data;
 ProValue		value = NULL;
 ProElement		elem;
 int			ii = 0, size = 0;
 static ElemTable	end_elem_table[] = 
 { 
   { PRO_E_HOLESET_END_TYPE,      PRO_VALUE_TYPE_INT    },
   { PRO_E_HOLESET_DEPTH_VALUE,   PRO_VALUE_TYPE_DOUBLE }
 };

 size = sizeof( end_elem_table )/ sizeof( ElemTable );

 for ( ii = 0 ; ii < size; ii++ )
 {
   if ( end_elem_table[ii].elem_type == PRO_E_HOLESET_DEPTH_VALUE &&
        end_type == PRO_DRILL_AUTO_END )
   {
     continue;
   }

   err = ProElementAlloc( end_elem_table[ii].elem_type, &elem );
   ERROR_CHECK( "UserHolesetEndSet","ProElementAlloc()", err );

   switch ( end_elem_table[ii].elem_type )
   {
     case PRO_E_HOLESET_END_TYPE:
        err = ProElementIntegerSet(elem, end_type);
        ERROR_CHECK( "UserHolesetEndSet"," ProElementIntegerSet()",err );
        break;

     case PRO_E_HOLESET_DEPTH_VALUE:
        err=ProElementDoubleSet(elem,depth);
        ERROR_CHECK("UserHolesetEndSet"," ProElementDoubleSet()",err);
        break;

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

   err = ProElemtreeElementAdd( end_elem, NULL, elem );
   ERROR_CHECK( "UserHolesetEndSet", "ProElemtreeElementAdd()", err );
 }

 return ( err );
}

/*====================================================================*\
FUNCTION : UserCsinkHolesetEndSet
PURPOSE  : Add a countersink diameter to holeset end element
\*====================================================================*/
ProError UserCsinkHolesetEndSet (
/*--------------------------------------------------------------------*/
double 		csink_diam,
ProElement	end_elem 

)
/*--------------------------------------------------------------------*/
{
 ProError		err = PRO_TK_NO_ERROR;
 ProValueData		value_data;
 ProValue		value = NULL;
 ProElement		elem;
 int			ii = 0, size = 0;
 static ElemTable	end_elem_table[] = 
 { 
   { PRO_E_HOLESET_CSINK_DIAM,  PRO_VALUE_TYPE_DOUBLE }
 };

 size = sizeof( end_elem_table )/ sizeof( ElemTable );

 for ( ii = 0 ; ii < size; ii++ )
 {
   err = ProElementAlloc( end_elem_table[ii].elem_type, &elem );
   ERROR_CHECK( "UserCsinkHolesetEndSet","ProElementAlloc()", err );

   switch ( end_elem_table[ii].elem_type )
   {
     case PRO_E_HOLESET_CSINK_DIAM:
	    err=ProElementDoubleSet(elem,csink_diam);
		ERROR_CHECK("UserCsinkHolesetEndSet", "ProElementDoubleSet()", err);
        break;

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

   err = ProElemtreeElementAdd( end_elem, NULL, elem );
   ERROR_CHECK( "UserCsinkHolesetEndSet", "ProElemtreeElementAdd()", err );
 }

 return ( err );
}

/*====================================================================*\
FUNCTION : UserHolesetRulesSet
PURPOSE  : Add individual axes selection to holeset rules
\*====================================================================*/
ProError UserHolesetRulesSet (
/*--------------------------------------------------------------------*/
ProSelection	*sel_axes,
ProElement	rules_elem 

)
/*--------------------------------------------------------------------*/
{
 ProError		err = PRO_TK_NO_ERROR;
 ProElement		elem = NULL;
 ProReference		*refs = NULL;

 err = ProElementAlloc( PRO_E_HOLESET_SEL_INDIV_AXES, &elem );
 ERROR_CHECK( "UserHolesetRulesSet","ProElementAlloc()", err );

 err = ProSelectionarrayToReferences( sel_axes, &refs );
 ERROR_CHECK( "UserHolesetRulesSet()", "ProSelectionToReference", err );

 err = ProElementReferencesSet( elem, refs );
 ERROR_CHECK( "UserHolesetRulesSet()", "ProElementReferenceSet", err );

 err = ProElemtreeElementAdd( rules_elem, NULL, elem );
 ERROR_CHECK( "UserHolesetRulesSet", "ProElemtreeElementAdd()", err );

 return ( err );
}

/*====================================================================*\
FUNCTION : UserCsinkAutoChamferHolesetRulesSet
PURPOSE  : Add auto-chamfer flag to rules
\*====================================================================*/
ProError UserCsinkAutoChamferHolesetRulesSet (
/*--------------------------------------------------------------------*/
ProElement	rules_elem 

)
/*--------------------------------------------------------------------*/
{
 ProError		err = PRO_TK_NO_ERROR;
 ProElement		element = NULL;

 err = ProElementAlloc( PRO_E_HOLESET_SEL_AUTO_CHAMFER, &element );
 ERROR_CHECK( "UserCsinkAutoChamferHolesetRulesSet",
              "ProElementAlloc()", err );

  err = ProElementIntegerSet(element, PRO_B_TRUE);
  ERROR_CHECK( "UserCsinkAutoChamferHolesetRulesSet"," ProElementIntegerSet()",err );
  
 err = ProElemtreeElementAdd( rules_elem, NULL, element );
 ERROR_CHECK( "UserCsinkAutoChamferHolesetRulesSet", 
              "ProElemtreeElementAdd()", err );

 return ( err );
}

/*====================================================================*\
FUNCTION : UserHolesetSet
PURPOSE  : Create PRO_E_HOLESET element 
\*====================================================================*/
ProError UserHolesetSet( 
/*--------------------------------------------------------------------*/
ProSelection	*axes,
ProElement	holeset_elem

)
/*--------------------------------------------------------------------*/
{
 ProError		err = PRO_TK_NO_ERROR;
 ProElement		element = NULL;
 ProSelection		selection;
 ProReference		reference;
 int			ii = 0, table_size = 0;
 static ElemTable	elem_table[] = 
 {
   { PRO_E_HOLESET_TYPE,            PRO_VALUE_TYPE_INT },
   { PRO_E_HOLESET_START,           COMPOUND           },
   { PRO_E_HOLESET_END,             COMPOUND           },
   { PRO_E_HOLESET_SELECTION_RULES, COMPOUND           }
 };

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

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

   switch ( elem_table[ii].elem_type )
   {
     case PRO_E_HOLESET_TYPE:
	      err = ProElementIntegerSet(element, PRO_HOLESET_DRILL_AXES);
          ERROR_CHECK("UserHolesetSet", " ProElementIntegerSet",err );
        break;

     case PRO_E_HOLESET_START:
        err = UserHolesetStartSet( PRO_DRILL_AUTO_START, NULL, element );
        ERROR_CHECK( "UserHolesetSet","UserHolesetStartSet()", err );
        break;

     case PRO_E_HOLESET_END:
        err = UserHolesetEndSet( PRO_DRILL_AUTO_END, 0.0, element );
        ERROR_CHECK( "UserHolesetSet","UserHolesetEndSet()", err );
        break;

     case PRO_E_HOLESET_SELECTION_RULES:
        err = UserHolesetRulesSet( axes, element );
        ERROR_CHECK( "UserHolesetSet","UserHolesetRulesSet()", err );
        break;

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

   err = ProElemtreeElementAdd( holeset_elem, NULL, element );
   ERROR_CHECK( "UserHolesetSet","ProElemtreeElementAdd", err );
 }

 return ( err );
}

/*====================================================================*\
FUNCTION : UserCsinkHolesetSet
PURPOSE  : Create PRO_E_HOLESET element for countersink holemaking
\*====================================================================*/
ProError UserCsinkHolesetSet( 
/*--------------------------------------------------------------------*/
double		csink_diam,
ProElement	holeset_elem

)
/*--------------------------------------------------------------------*/
{
 ProError		err = PRO_TK_NO_ERROR;
 ProElement		element = NULL;
 ProValueData		value_data;
 ProValue		value;
 int			ii = 0, table_size = 0;
 static ElemTable	elem_table[] = 
 {
   { PRO_E_HOLESET_TYPE,            PRO_VALUE_TYPE_INT },
   { PRO_E_HOLESET_END,             COMPOUND           },
   { PRO_E_HOLESET_SELECTION_RULES, COMPOUND           }
 };

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

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

   switch ( elem_table[ii].elem_type )
   {
     case PRO_E_HOLESET_TYPE:  
	      err = ProElementIntegerSet(element,PRO_HOLESET_DRILL_AXES );
          ERROR_CHECK( "UserCsinkHolesetSet"," ProElementIntegerSet()",err);
		  break;
		  
     case PRO_E_HOLESET_END:
        err = UserCsinkHolesetEndSet( csink_diam, element );
        ERROR_CHECK( "UserCsinkHolesetSet","UserCsinkHolesetEndSet()", err );
        break;

     case PRO_E_HOLESET_SELECTION_RULES:
        err = UserCsinkAutoChamferHolesetRulesSet( element );
        ERROR_CHECK( "UserHolesetSet","UserHolesetRulesSet()", err );
        break;

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

   err = ProElemtreeElementAdd( holeset_elem, NULL, element );
   ERROR_CHECK( "UserCsinkHolesetSet","ProElemtreeElementAdd", err );
 }

 return ( err );
}

/*====================================================================*\
FUNCTION : UserHolesetArrSet
PURPOSE  : Create holesets array element
\*====================================================================*/
ProError UserDrillHolesetArrSet(
/*--------------------------------------------------------------------*/
ProSelection    *axes,
ProElement      holesets_elem

)
/*--------------------------------------------------------------------*/
{
 ProError               err = PRO_TK_NO_ERROR;
 ProElement             element = NULL;
 int                    ii;
 int                    num_holesets = 1; /* can be more if needed */

 for ( ii = 0; ii < num_holesets; ii++ )
 {
   err = ProElementAlloc( PRO_E_HOLESET, &element );
   ERROR_CHECK( "UserHolesetArrSet", "ProElementAlloc", err );

   err = UserHolesetSet( axes, element );
   ERROR_CHECK( "UserHolesetArrSet", "UserHolesetSet", err );

   err = ProElemtreeElementAdd( holesets_elem, NULL, element );
   ERROR_CHECK( "UserHolesetArrSet","ProElemtreeElementAdd", err );
 }

 return ( err );
}

/*====================================================================*\
FUNCTION : UserCsinkHolesetArrSet
PURPOSE  : Create holesets array element
\*====================================================================*/
ProError UserCsinkHolesetArrSet(
/*--------------------------------------------------------------------*/
double		csink_diam,
ProElement      holesets_elem

)
/*--------------------------------------------------------------------*/
{
 ProError               err = PRO_TK_NO_ERROR;
 ProElement             element = NULL;
 int                    ii;
 int                    num_holesets = 1; /* can be more if needed */

 for ( ii = 0; ii < num_holesets; ii++ )
 {
   err = ProElementAlloc( PRO_E_HOLESET, &element );
   ERROR_CHECK( "UserCsinkHolesetArrSet", "ProElementAlloc", err );

   err = UserCsinkHolesetSet( csink_diam, element );
   ERROR_CHECK( "UserCsinkHolesetArrSet", "UserHolesetSet", err );

   err = ProElemtreeElementAdd( holesets_elem, NULL, element );
   ERROR_CHECK( "UserCsinkHolesetArrSet","ProElemtreeElementAdd", err );
 }

 return ( err );
}