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

#include <ProFeatType.h>
#include <ProToolkit.h>
#include <ProFeature.h>
#include <ProSelbuffer.h>
#include <ProReference.h>
#include <ProUtil.h>
#include <ProSmtFlatWall.h>
#include <ProSmtExtendWall.h>
#include <ProSheetmetal.h>
#include <ProMenuBar.h>
#include <ProPopupmenu.h>
#include <ProMdl.h>
#include <PTApplsUnicodeUtils.h>
#include <ProEdge.h>

ProBoolean UserEdgeIsSmtFaceEdge (ProGeomitem* edge);


/*=====================================================================*\
FUNCTION: UserSmtExtendWallCreate
PURPOSE:  Create sheetmetal extend wall features.
\*=====================================================================*/
/*ARGSUSED*/
int UserSmtExtendWallCreate ( ProReference edge_ref ) 
{ 
  ProElement pro_e_feature_tree;
  ProElement pro_e_feature_type;
  ProElement pro_e_smt_wall_type;
  ProElement pro_e_smt_extend_wall_edge;

  ProElement pro_e_smt_extend_wall_dist;
     ProElement pro_e_step_extend_wall_dist_type;
     ProElement pro_e_smt_extend_dist_ref;

  ProElement pro_e_smt_extend_wall_extensions_cmp;

     ProElement pro_e_smt_extend_side1_extension_cmp;
        ProElement pro_e_smt_extend_extension_type_opt;
        ProElement pro_e_smt_extend_adjust_srf;

     ProElement pro_e_smt_extend_side2_extension_cmp;


  ProMdl model;
  ProModelitem model_item;
  ProFeatureCreateOptions *opts = 0;
  ProSelection model_sel;
  ProFeature feature;
  ProErrorlist errors;
  ProError status;
  ProSelection feat_sel;


/*-----------------------------------------------------------------*\
Processing Element PRO_E_FEATURE_TREE
\*-----------------------------------------------------------------*/
  status = ProElementAlloc ( PRO_E_FEATURE_TREE, &pro_e_feature_tree ); 

/*-----------------------------------------------------------------*\
Processing Element PRO_E_FEATURE_TYPE
\*-----------------------------------------------------------------*/
  status = ProElementAlloc ( PRO_E_FEATURE_TYPE, &pro_e_feature_type );
  status = ProElementIntegerSet ( pro_e_feature_type, PRO_FEAT_WALL );
  status = ProElemtreeElementAdd ( pro_e_feature_tree, NULL, 
				   pro_e_feature_type );

/*-----------------------------------------------------------------*\
Processing Element PRO_E_SMT_WALL_TYPE
\*-----------------------------------------------------------------*/
  status = ProElementAlloc ( PRO_E_SMT_WALL_TYPE, &pro_e_smt_wall_type );
  status = ProElementIntegerSet ( pro_e_smt_wall_type, 
			          PRO_SMT_WALL_TYPE_EXTEND );
  status = ProElemtreeElementAdd ( pro_e_feature_tree, NULL, 
				   pro_e_smt_wall_type );

/*-----------------------------------------------------------------*\
Processing Element PRO_E_SMT_EXTEND_WALL_EDGE
\*-----------------------------------------------------------------*/
  status = ProElementAlloc ( PRO_E_SMT_EXTEND_WALL_EDGE, 
			     &pro_e_smt_extend_wall_edge );
  status = ProElementReferenceSet( pro_e_smt_extend_wall_edge, edge_ref );
  status = ProElemtreeElementAdd ( pro_e_feature_tree, NULL, 
				   pro_e_smt_extend_wall_edge );


/*-----------------------------------------------------------------*\
Processing Element PRO_E_SMT_EXTEND_WALL_DIST
\*-----------------------------------------------------------------*/
 status = ProElementAlloc ( PRO_E_SMT_EXTEND_WALL_DIST,
                            &pro_e_smt_extend_wall_dist );
 status = ProElemtreeElementAdd ( pro_e_feature_tree, NULL, 
				  pro_e_smt_extend_wall_dist );


/*-----------------------------------------------------------------*\
Processing Element PRO_E_SMT_EXTEND_DIST_TYPE
\*-----------------------------------------------------------------*/
  status = ProElementAlloc ( PRO_E_SMT_EXTEND_DIST_TYPE, 
			     &pro_e_step_extend_wall_dist_type );
  status = ProElementIntegerSet ( pro_e_step_extend_wall_dist_type,
				  PRO_EXTEND_DIST_BY_VALUE );
  status = ProElemtreeElementAdd ( pro_e_smt_extend_wall_dist, NULL, 
				   pro_e_step_extend_wall_dist_type );

/*-----------------------------------------------------------------*\
Processing Element PRO_E_SMT_EXTEND_DIST_REF
\*-----------------------------------------------------------------*/
  status = ProElementAlloc ( PRO_E_SMT_EXTEND_DIST_REF, 
			     &pro_e_smt_extend_dist_ref );
  status = ProElementReferenceSet( pro_e_smt_extend_dist_ref,
                                   (ProReference)NULL );
  status = ProElemtreeElementAdd ( pro_e_smt_extend_wall_dist, NULL, 
				   pro_e_smt_extend_dist_ref );


/*-----------------------------------------------------------------*\
Processing Element PRO_E_SMT_EXTEND_WALL_EXTENSIONS_CMP
\*-----------------------------------------------------------------*/
 status = ProElementAlloc ( PRO_E_SMT_EXTEND_WALL_EXTENSIONS_CMP,
                            &pro_e_smt_extend_wall_extensions_cmp );
 status = ProElemtreeElementAdd ( pro_e_feature_tree, NULL, 
				  pro_e_smt_extend_wall_extensions_cmp );

/*-----------------------------------------------------------------*\
Processing Element PRO_E_SMT_EXTEND_SIDE1_EXTENSION_CMP
\*-----------------------------------------------------------------*/
 status = ProElementAlloc ( PRO_E_SMT_EXTEND_SIDE1_EXTENSION_CMP,
                            &pro_e_smt_extend_side1_extension_cmp );
 status = ProElemtreeElementAdd ( pro_e_smt_extend_wall_extensions_cmp, NULL, 
				  pro_e_smt_extend_side1_extension_cmp );

/*-----------------------------------------------------------------*\
Processing Element PRO_E_SMT_EXTEND_SIDE2_EXTENSION_CMP
\*-----------------------------------------------------------------*/
 status = ProElementAlloc ( PRO_E_SMT_EXTEND_SIDE2_EXTENSION_CMP,
                            &pro_e_smt_extend_side2_extension_cmp );
 status = ProElemtreeElementAdd ( pro_e_smt_extend_wall_extensions_cmp, NULL, 
				  pro_e_smt_extend_side2_extension_cmp );

/*-----------------------------------------------------------------*\
Processing Element PRO_E_SMT_EXTEND_EXTENSION_TYPE_OPT
\*-----------------------------------------------------------------*/
  status = ProElementAlloc ( PRO_E_SMT_EXTEND_ADJUST_SRF, 
			     &pro_e_smt_extend_extension_type_opt );
  status = ProElementIntegerSet ( pro_e_smt_extend_extension_type_opt,
				  PRO_EXTEND_EXT_NORMAL_TO_EDGE );
  status = ProElemtreeElementAdd ( pro_e_smt_extend_side1_extension_cmp , NULL, 
				   pro_e_smt_extend_extension_type_opt );
  status = ProElemtreeElementAdd ( pro_e_smt_extend_side2_extension_cmp , NULL, 
				   pro_e_smt_extend_extension_type_opt );


/*-----------------------------------------------------------------*\
Processing Element PRO_E_SMT_EXTEND_ADJUST_SRF
\*-----------------------------------------------------------------*/
  status = ProElementAlloc ( PRO_E_SMT_EXTEND_ADJUST_SRF, 
			     &pro_e_smt_extend_adjust_srf );
  status = ProElementIntegerSet ( pro_e_smt_extend_adjust_srf,
				  PRO_EXTEND_ADJ_SRF_FALSE );
  status = ProElemtreeElementAdd ( pro_e_smt_extend_side1_extension_cmp , NULL, 
				  pro_e_smt_extend_adjust_srf );
  status = ProElemtreeElementAdd ( pro_e_smt_extend_side2_extension_cmp , NULL, 
				  pro_e_smt_extend_adjust_srf );


/*-----------------------------------------------------------------*\
Create the feature using the element tree
\*-----------------------------------------------------------------*/
 status = ProMdlCurrentGet (&model);
 status = ProMdlToModelitem( model, &model_item );
 status = ProSelectionAlloc (NULL, &model_item, &model_sel);



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

  opts[0]= PRO_FEAT_CR_NO_OPTS;

 status = ProFeatureWithoptionsCreate (model_sel, pro_e_feature_tree,
    opts, PRO_REGEN_NO_FLAGS, &feature, &errors);

  status = ProArrayFree((ProArray*)&opts);
 if (status == PRO_TK_NO_ERROR)
 {
	 ProSelectionAlloc (NULL, &feature, &feat_sel);
	 ProSelbufferClear ();
	 ProSelbufferSelectionAdd (feat_sel);
	 ProSelectionFree (&feat_sel);
 }

 return (PRO_TK_NO_ERROR);
}


/*=====================================================================*\
FUNCTION: UserSmtExtendWallCreate_OA_Thickness
PURPOSE:  Create sheetmetal extend wall features using Object/Action 
          selection.
\*=====================================================================*/
int UserSmtExtendWallCreate_OA_Thickness ()
{
  ProSelection* sel;
  ProReference reference;
    
/*-----------------------------------------------------------------*\
Extract the current selected edge or edge chain as the wall attachment
\*-----------------------------------------------------------------*/
  ProSelbufferSelectionsGet (&sel);

  ProSelectionToReference ( sel[0], &reference );
  

/*-----------------------------------------------------------------*\
Create the feature with the extracted information
\*-----------------------------------------------------------------*/
  UserSmtExtendWallCreate ( reference );

  ProReferenceFree (reference);

  return (PRO_TK_NO_ERROR);
}

#define OA 1  /* Standard OA in the menu system, typically gray out 
		 the button when not usable*/
#define PM 2 /* OA in a popup menu, typically remove the button when 
	         not usable */

/*=====================================================================*\
FUNCTION: UserSmtExtendWallCreate_TestLow
PURPOSE:  Access function for the button for smt extend wall feature creation
\*=====================================================================*/
static uiCmdAccessState UserSmtExtendWallCreate_TestLow (ProSelection* sels, 
						       int mode)
{
  uiCmdAccessState access_result;
  ProBoolean should_free = PRO_B_FALSE;
  ProError status;
  ProMdl mdl;
  ProMdlType type;
  ProMdlsubtype subtype;
  ProReference reference;
  ProModelitem item;
  ProEdge edge;
  ProEnttype ent_type;
  int size;

/*-----------------------------------------------------------------*\
  Set the default return if the button is unusable.
\*-----------------------------------------------------------------*/  
  if (mode == OA)
    access_result = ACCESS_UNAVAILABLE;
  else 
    access_result = ACCESS_REMOVE;

  status = ProMdlCurrentGet (&mdl);

  if (status != PRO_TK_NO_ERROR)
    return (access_result);

  status = ProMdlTypeGet (mdl, &type);

  status = ProMdlSubtypeGet (mdl, &subtype);
  
  if (type != PRO_MDL_PART || subtype != PROMDLSTYPE_PART_SHEETMETAL)
    return (access_result);

/*-----------------------------------------------------------------*\
  If called without selections, extract the current selections from
  the buffer.
\*-----------------------------------------------------------------*/ 
  if (sels == NULL)
    {   
      status = ProSelbufferSelectionsGet (&sels);
      
      if (status != PRO_TK_NO_ERROR)
	return access_result;

      if (sels == NULL)
	return access_result;

      should_free = PRO_B_TRUE;
    }

/*-----------------------------------------------------------------*\
  This command allows only one selection.
\*-----------------------------------------------------------------*/   
  status = ProArraySizeGet (sels, &size);
  
  if (status != PRO_TK_NO_ERROR)
    return access_result;

  if (size == 1)
  {
/*-----------------------------------------------------------------*\
Extract the reference edge selected by the user
\*-----------------------------------------------------------------*/    
    status = ProSelectionToReference (sels [0], &reference);
    ProTKPrintf ("Status of ProSelectionCollectionGet: %d\n\n", status);

    if (status == PRO_TK_NO_ERROR)
	{
/*-----------------------------------------------------------------*\
Check the reference to ensure that the reference is an edge 
which borders a sheetmetal face.
\*-----------------------------------------------------------------*/
	  ProReferenceTypeGet (reference, &item.type);
	  
	  if (item.type == PRO_EDGE)
	  {
	      
	      ProReferenceOwnerGet (reference, &item.owner);
	      ProReferenceIdGet (reference, &item.id);
	      
	      ProReferenceFree (reference);
	      
	    if (UserEdgeIsSmtFaceEdge (&item))
		{

/*-----------------------------------------------------------------*\
Extend wall attachment edge must be straight
\*-----------------------------------------------------------------*/
		  ProGeomitemToEdge (&item, &edge);
		  
		  ProEdgeTypeGet (edge, &ent_type);
		  
		  if (ent_type == PRO_ENT_LINE)
		  {
/*-----------------------------------------------------------------*\
If reference is OK, the button should be active.
\*-----------------------------------------------------------------*/
		      access_result = ACCESS_AVAILABLE;
		  }
		}
	  }
    }
  }
  
  if (should_free)
    ProSelectionarrayFree (sels);
      
  return access_result;
}

/*=====================================================================*\
FUNCTION: UserSmtExtendWallCreate_TestMdlTree
PURPOSE:  Access function for the model tree popup menu button.	
\*=====================================================================*/
/*ARGSUSED*/
uiCmdAccessState UserSmtExtendWallCreate_TestMdlTree (uiCmdAccessMode mode)
{ 
  return UserSmtExtendWallCreate_TestLow (NULL, PM);
}


/*=====================================================================*\
FUNCTION: UserSmtExtendWallCreate_TestPM
PURPOSE:  Access function for the graphics window popup menu button.	
\*=====================================================================*/
/*ARGSUSED*/
uiCmdAccessState UserSmtExtendWallCreate_TestPM (uiCmdCmdId id,
				      ProAppData data,
				      ProSelection* sels)
{ 
  return UserSmtExtendWallCreate_TestLow (sels, PM);
}

#undef OA

#undef PM