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

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

extern ProLine  msg_fil17;
#define MSG_FIL ProStringToWstring(msg_fil17,"msg_ugmfg.txt")

typedef struct { 
    ProMfg       model;
    ProSelection workcell;
    ProBoolean   wc_found;
    ProSelection csys;
    ProBoolean   csys_found;
} OperEnts ;

/*====================================================================*\
Function : UserOperCsysGeomitemGet
Purpose  : Get geom item
\*====================================================================*/
static ProError UserOperCsysGeomitemGet (
/*--------------------------------------------------------------------*/
ProGeomitem	*geomitem,
ProError	status,
ProAppData	app_data

)
/*--------------------------------------------------------------------*/
{
 *(ProGeomitem*)app_data = *geomitem;

 return ( PRO_TK_NO_ERROR );
}

/*====================================================================*\
Function : UserOperEnitiesCollect
Purpose  : Collect worckcell and csys and use them to create an operation
\*====================================================================*/
ProError UserOperEnitiesCollect (
/*--------------------------------------------------------------------*/
ProFeature	*feature,
ProError	err,
ProAppData	entities 

)
/*--------------------------------------------------------------------*/
{
 ProError	status;
 ProAsmcomppath	path;
 ProFeattype	feat_type;
 ProWcellType	wcell_type;
 OperEnts	*oper_ents = (OperEnts*)entities;
 ProSelection	selection;
 ProGeomitem	csysgeom;
 int		id;

 status = ProFeatureTypeGet( feature, &feat_type );
 ERROR_CHECK( "UserOperEnitiesCollect","ProFeatureTypeGet()",status );

 if ( status == PRO_TK_NO_ERROR )
 {
   if ( !oper_ents->wc_found && feat_type == PRO_FEAT_WORKCELL )
   {
     status = ProSelectionAlloc( NULL, feature, &selection );
     ERROR_CHECK( "UserOperEnitiesCollect", "ProSelectionAlloc()", 
                  status );

     ProSelectionCopy( selection, &oper_ents->workcell );
     oper_ents->wc_found = PRO_B_TRUE;
   }
   else if ( !oper_ents->csys_found && feat_type == PRO_FEAT_CSYS )
   {
     status = ProFeatureGeomitemVisit( feature, PRO_CSYS,
                                       UserOperCsysGeomitemGet, NULL, 
                                       &csysgeom );
     ERROR_CHECK( "UserOperEnitiesCollect", "ProFeatureGeomitemVisit()", 
                  status );

     status = ProSelectionAlloc( NULL, (ProModelitem*)&csysgeom, &selection );
     ERROR_CHECK( "UserOperEnitiesCollect", "ProFeatureSelectionCreate()", 
                  status);

     ProSelectionCopy( selection, &oper_ents->csys );
     oper_ents->csys_found = PRO_B_TRUE;
   }
 }

 if ( oper_ents->wc_found && oper_ents->csys_found )
   return ( PRO_TK_STOP_VISIT );

 return ( PRO_TK_NO_ERROR );
}

/*====================================================================*\
FUNCTION : UserOperCreate
PURPOSE  : Top level operation creation function 
\*====================================================================*/
int UserOperCreate ()
{
 ProMdl		mfg_model;
 ProError	status;
 ProSolid	mfg_solid;
 OperEnts	entities;

 ProError UserOperationCreate ();

 wchar_t  feat_name[PRO_NAME_SIZE], def_wname[PRO_NAME_SIZE];
 char     def_name[] = "DemoOp", str[PRO_LINE_SIZE];

 status = ProMdlCurrentGet( &mfg_model );
 ERROR_CHECK( "UserOperCreate", "ProMdlCurrentGet", status );
 
 if ( status == PRO_TK_NO_ERROR )
 {
   status = ProMfgSolidGet( (ProMfg)mfg_model, &mfg_solid );
   ERROR_CHECK( "UserOperCreate", "ProMfgSolidGet", status );
 }

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

 /*----------------------------------------*\
    Search required references
 \*----------------------------------------*/
 entities.wc_found = PRO_B_FALSE;
 entities.csys_found = PRO_B_FALSE;
 entities.model = (ProMfg)mfg_model;

 status = ProSolidFeatVisit( mfg_solid, UserOperEnitiesCollect, NULL,
                            (ProAppData) &entities ); 

 if ( entities.wc_found == PRO_B_TRUE && entities.csys_found == PRO_B_TRUE )
 {
   /*----------------------------------------*\
      Create operation
   \*----------------------------------------*/
   ProMessageDisplay( MSG_FIL, "USER Enter operation name: ");
   ProStringToWstring( def_wname, def_name );
   ProUtilStringGet( feat_name, def_wname, PRO_NAME_SIZE);
	
   status = UserOperationCreate( (ProMfg)mfg_model, feat_name, 
                                 entities.workcell,  entities.csys );
   ERROR_CHECK("UserOperCreate","UserOperationCreate",status);
 }
 else
 {
   if ( !entities.wc_found )
     ProTKFprintf( stderr, "A suitable worckcell was not found\n" );

   if ( !entities.csys_found )
     ProTKFprintf( stderr, "A suitable coord-sys was not found\n" );
 }
    
 return ( (int)status );
}

/*====================================================================*\
Function :  UserOperationCreate
Purpose  : Create operation using element tree
\*====================================================================*/
ProError UserOperationCreate (
/*--------------------------------------------------------------------*/
ProMfg		mfg_model,
ProName		feat_name,
ProSelection	workcell,
ProSelection	csys_sel 

)
/*--------------------------------------------------------------------*/
{
 ProError       err = PRO_TK_NO_ERROR;
 ProElement     oper_elem = NULL;      /* Individual element */
 ProElement     oper_elem_tree = NULL; /* Entire tree        */
 ProErrorlist   errors;
 ProSolid       mfg_solid;
 ProModelitem   modelitem;
 ProSelection   selection;
 ProFeature     oper_feature;
 ProReference   reference;
 int            ii = 0, size = 0;

 static ElemTable  oper_elem_table[] =  
 {
   { PRO_E_FEATURE_TYPE,     PRO_VALUE_TYPE_INT       },
   { PRO_E_MFG_WCELL_REF,    PRO_VALUE_TYPE_SELECTION },
   { PRO_E_OPER_CSYS,        PRO_VALUE_TYPE_SELECTION },
   { PRO_E_STD_FEATURE_NAME, PRO_VALUE_TYPE_WSTRING   }
 };
		
 size = sizeof(oper_elem_table)/ sizeof(ElemTable);

 err = ProElementAlloc( PRO_E_FEATURE_TREE, &oper_elem_tree );
 ERROR_CHECK( "UserOperationCreate","ProElementAlloc()", err );
    
 for ( ii = 0; ii < size; ii++ )
 {
   err = ProElementAlloc( oper_elem_table[ii].elem_type, &oper_elem );
   ERROR_CHECK( "UserOperationCreate","ProElementAlloc()", err );

   switch ( oper_elem_table[ii].elem_type )
   {
     case PRO_E_FEATURE_TYPE:
		err = ProElementIntegerSet ( oper_elem, PRO_FEAT_OPERATION );
        ERROR_CHECK( "UserOperationCreate"," ProElementIntegerSet",err );
        break;

     case PRO_E_MFG_WCELL_REF:
		err = ProSelectionToReference( workcell, &reference );
        ERROR_CHECK( "UserOperationCreate()", "ProSelectionToReference", err );

        err = ProElementReferenceSet( oper_elem, reference );
        ERROR_CHECK( "UserOperationCreate()", "ProElementReferenceSet", err );
	break;

     case PRO_E_OPER_CSYS:
		err = ProSelectionToReference( csys_sel, &reference );
        ERROR_CHECK( "UserOperationCreate()", "ProSelectionToReference", err );

        err = ProElementReferenceSet( oper_elem, reference );
        ERROR_CHECK( "UserOperationCreate()", "ProElementReferenceSet", err );
        break;

     case PRO_E_STD_FEATURE_NAME:
		  err=ProElementWstringSet(oper_elem, feat_name);
		  ERROR_CHECK( "UserOperationCreate()"," ProElementWstringSet" ,err);
	break;

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

   err = ProElemtreeElementAdd( oper_elem_tree, NULL, oper_elem );
   ERROR_CHECK( "UserOperationCreate", "ProElemtreeElementAdd()", err );
 }

 ProUtilElementtreePrint( oper_elem_tree, PRO_TEST_INFO_WINDOW, NULL );

 /*********************************************/
 /* Create feature                            */
 /*********************************************/
 err = UserMfgModelFeatureCreate( mfg_model, oper_elem_tree, &oper_feature );
 ERROR_CHECK( "UserOperationCreate", "UserMfgModelFeatureCreate()", err );

 err = ProElementFree( &oper_elem_tree);
 ERROR_CHECK( "UserOperationCreate", "ProElementFree()", err );

 return ( (int)err );
}

#undef MSG_FIL