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


/*--------------------------------------------------------------------*\
Pro/Toolkit includes
\*--------------------------------------------------------------------*/
#include <ProToolkit.h>
#include <ProMdl.h>
#include <ProFeature.h>
#include <ProSolid.h>
#include <ProModelitem.h>
#include <ProGeomitem.h>
#include <ProEdge.h>
#include <ProAxis.h>
#include <ProCsys.h>
#include <ProSurface.h>
#include <ProFeatType.h>
#include <ProPoint.h>
#include <ProCurve.h>
#include <ProQuilt.h>
#include <ProArray.h>
#include <ProSelection.h>
#include <ProMenu.h>
#include <ProUtil.h>

#include "UtilGeom.h"
#include "UtilColor.h"
#include "TestConsts.h"
#include "TestError.h"
#include "TestMisc.h"
#include "UtilVisit.h"
#include "UtilCollect.h"
#include "UtilTypes.h"
#include <PTApplsUnicodeUtils.h>
#include "ProNotify.h"
#include "UtilMessage.h"
#include "UtilFiles.h"
#include "UtilFeats.h"
/*--------------------------------------------------------------------*\
Application macros
\*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*\
Application data types
\*--------------------------------------------------------------------*/
#define FEAT_LIST	1
typedef struct testfeatdata
{
    unsigned int action; /* Bit map of FEAT_... */
    void *data;
} ProTestFeatData;


typedef struct {    /* added due to change to ProQuilt */
    ProMdl owner;
    FILE *fp;
} TestAppdata;

typedef struct {
    ProFeattype feat_type;
    ProType     geom_type;
    char        name_pref[11];
} GeomLookup ;

static GeomLookup lookup_table[] = {
{ PRO_FEAT_HOLE, PRO_AXIS, "tk_axis" },
{ PRO_FEAT_FIRST_FEAT, PRO_EDGE, "tk_edge" },
{ PRO_FEAT_PROTRUSION, PRO_EDGE, "tk_edge" },
{ PRO_FEAT_ROUND, PRO_SURFACE, "tk_surf" },
{ PRO_FEAT_CSYS, PRO_CSYS, "tk_csys" },
{ PRO_FEAT_CURVE, PRO_CURVE, "tk_curve" },
{ PRO_FEAT_DATUM_SURF, PRO_QUILT, "tk_surface" },
{ PRO_FEAT_DATUM_QUILT, PRO_SURFACE, "tk_surface" },
{ PRO_FEAT_DATUM_POINT, PRO_POINT, "tk_point" },
{ PRO_TK_NOT_USED,  PRO_FEATURE, "tk_feat" }};

static int table_size = sizeof(lookup_table)/sizeof(GeomLookup);
static int suff_num = 1;
static int feature_number = 0;
static ProError ProTestCustomFileOpen();
static ProError ProTestCustomFileSave();
ProBoolean PTTestOpenAccessFunction (wchar_t* file_type, ProAppData app_data );
ProError PTTestOpenOperationAction (wchar_t* file_type, ProPath file_path, ProAppData app_data );
ProBoolean PTTestSaveAccessFunction (wchar_t* file_type, ProMdl model,  ProAppData app_data );
ProError PTTestSaveOperationAction (wchar_t* file_type, ProMdl model, ProPath file_path, ProAppData app_data );
ProError ProSampCustomFileOpen();
ProError ProOpenOk(ProMdlType mdl_type, int sub_type, ProName model_name);
ProError ProTestFeatureInfoAct(ProModelitem *feature, ProError instatus, ProAppData appdata);
int ProTestFeatureInfoGeom(ProModelitem *feature, FILE *fp);
ProError ProTestGeomitemInfoAct(ProGeomitem *item, ProError instatus, ProAppData appdata); 
/*====================================================================*\
FUNCTION : ProTestMisc
PURPOSE  : 
\*====================================================================*/
int ProTestMisc(ProSolid* p_solid)
{
    ProError status;
    ProMdl   model;
    MafpInfo mafpinf;
    int      id;


    if ((mafpinf.fp = PTApplsUnicodeFopen("misc_test.inf", "w")) == NULL)
        return PRO_TK_GENERAL_ERROR;

    status = ProMdlCurrentGet(&model);
    TEST_CALL_REPORT("ProMdlCurrentGet()", 
	"ProTestMiscMenu()", status, status!=PRO_TK_NO_ERROR);

  
    mafpinf.p_model = &model;

    status = ProMenuFileRegister((char*)"tk_misc", (char*)"tk_misc.mnu", &id);
    TEST_CALL_REPORT ("ProMenuFileRegister", "ProTestMiscMenu",
        status, status != PRO_TK_NO_ERROR);
        
    status = ProMenubuttonActionSet((char*)"tk_misc",(char*)"-Init Test",
	(ProMenubuttonAction)ProTestFuncInit, (void *) &mafpinf,0);
    TEST_CALL_REPORT ("ProMenubuttonActionSet", "ProTestMiscMenu",
        status, status != PRO_TK_NO_ERROR);
        
    status = ProMenubuttonActionSet((char*)"tk_misc",(char*)"-Name Get",
	(ProMenubuttonAction)ProTestMdlNameGet, (void *) mafpinf.fp,0);
    TEST_CALL_REPORT ("ProMenubuttonActionSet", "ProTestMiscMenu",
        status, status != PRO_TK_NO_ERROR);
      /*  Example added from the project 13014507 */  
    status = ProMenubuttonActionSet((char*)"tk_misc",(char*)"-Custom File Open",
	(ProMenubuttonAction)ProTestCustomFileOpen, (void *) mafpinf.fp,0);
    TEST_CALL_REPORT ("ProMenubuttonActionSet", "ProTestMiscMenu",
        status, status != PRO_TK_NO_ERROR); 
        
    status = ProMenubuttonActionSet((char*)"tk_misc",(char*)"-Custom File Save",
	(ProMenubuttonAction)ProTestCustomFileSave, (void *) mafpinf.fp,0);
    TEST_CALL_REPORT ("ProMenubuttonActionSet", "ProTestMiscMenu",
        status, status != PRO_TK_NO_ERROR);        
         
    status = ProMenubuttonActionSet((char*)"tk_misc",(char*)"tk_misc",
	(ProMenubuttonAction)ProTestMiscFpClose, (void *) mafpinf.fp,0);
    TEST_CALL_REPORT ("ProMenubuttonActionSet", "ProTestMiscMenu",
        status, status != PRO_TK_NO_ERROR);

    status = ProMenuCreate(PROMENUTYPE_MAIN,(char*)"tk_misc", &id);
    TEST_CALL_REPORT ("ProMenuCreate", "ProTestMiscMenu",
        status, status != PRO_TK_NO_ERROR);
    status = ProMenuProcess((char*)"tk_misk", &id);
    TEST_CALL_REPORT ("ProMenuProcess", "ProTestMiscMenu",
        status, status != PRO_TK_NO_ERROR);
    return PRO_TK_NO_ERROR;
}

/*====================================================================*\
FUNCTION : ProTestMiscFpClose
PURPOSE  : Close file pointer opened
\*====================================================================*/
int ProTestMiscFpClose (FILE *fp)
{
    ProError status;
    fclose(fp);
    status = ProMenuDelete();
    TEST_CALL_REPORT ("ProMenuDelete", "ProTestMiscFpClose",
        status, status != PRO_TK_NO_ERROR);
    return 0;
}


/*====================================================================*\
FUNCTION : ProTestFuncInit
PURPOSE  : Top level test
\*====================================================================*/
int ProTestFuncInit (MafpInfo *p_mafpinf)
{
    ProError status;
    
    status = ProUtilFeatvisVisit((ProSolid)p_mafpinf->p_model[0], 
	(ProFunction)ProTestFeatAct, (ProAppData)p_mafpinf->fp);
        
    return PRO_TK_NO_ERROR;
}

/*====================================================================*\
FUNCTION : ProTestFeatAct
PURPOSE  : 
\*====================================================================*/
ProError ProTestFeatAct (
    ProFeature *p_feature,
    ProError err,
    ProAppData tmp_fp)
{
    ProError status;
    ProFeattype feat_type;
    ProFeature new_feat;
    int         i;
    ProSolid   owner;
    wchar_t    feat_name[PRO_NAME_SIZE];
    char       name[PRO_NAME_SIZE];
    ProBoolean visited = PRO_B_FALSE;
    FILE *fp = (FILE *) tmp_fp;

    ProError ProTestQuiltVisAct(ProGeomitem *p_geom_item, 
   		 ProError err,  FILE *fp);
/*--------------------------------------------------------------------*\
    An unnecessary ammount of function calls!!
\*--------------------------------------------------------------------*/
    status = ProFeatureSolidGet(p_feature, &owner);
    TEST_CALL_REPORT("ProFeatureSolidGet()", 
	    "ProTestFeatAct()", status, status!=PRO_TK_NO_ERROR);

    status = ProModelitemNameGet(p_feature, feat_name);
    TEST_CALL_REPORT("ProModelitemNameGet()", 
	    "ProTestFeatAct()", status, status!=PRO_TK_NO_ERROR);

    status = ProFeatureInit(owner, p_feature->id, &new_feat);
    TEST_CALL_REPORT("ProFeatureInit()", 
	    "ProTestFeatAct()", status, status!=PRO_TK_NO_ERROR);

    status = ProFeatureTypeGet(&new_feat, &feat_type);
    TEST_CALL_REPORT("ProFeatureTypeGet()", 
	    "ProTestFeatAct()", status, status!=PRO_TK_NO_ERROR);

    if ( status == PRO_TK_NO_ERROR)
    {
	ProTKFprintf(fp, "Feature Name before rename : %s\n", 
				    ProWstringToString(name, feat_name));
	status = ProTestNameGen((ProType)feat_type, feat_name);   
	if (status == PRO_TK_NO_ERROR)
	{
	    status = ProModelitemNameSet(p_feature, feat_name);
	    TEST_CALL_REPORT("ProModelitemNameSet()", 
		    "ProTestFeatAct()", status, status!=PRO_TK_NO_ERROR);
	    ProTKFprintf(fp, "Feature Name after rename  : %s\n", 
					ProWstringToString(name, feat_name));
	}
    }
    else
    {
	ProTKFprintf(fp,"No rename occured\n");
    }


/*--------------------------------------------------------------------*\
    Depending on feature type visit a different geometry item
\*--------------------------------------------------------------------*/
    for (i=0; i < table_size; i++)
    {
	if (lookup_table[i].feat_type == feat_type)
	{
	    ProTKFprintf(fp, "Found feature, visiting %s\n", lookup_table[i].name_pref);
	    if ( lookup_table[i].geom_type == PRO_QUILT)
	    {
#ifndef PT_PRODUCTS_BUILD
		status = ProUtilGeomitemactiveVisit(&new_feat, PRO_QUILT,
			    (ProFunction) ProTestQuiltVisAct, 
			    (ProAppData) fp);
#endif /* #ifndef PT_PRODUCTS_BUILD */
	    }
	    else
	    {
		status = ProUtilGeomitemactiveVisit(&new_feat, 
			    lookup_table[i].geom_type,
			    (ProFunction) ProTestGeomitemVisAct, 
			    (ProAppData) fp);
	    }
	    visited = PRO_B_TRUE;
	}
    }

    if ( visited == PRO_B_FALSE )
    {
	ProTKFprintf(fp, "Feature skipped\n");
	ProTKFprintf(fp, "Feature skipped\n");
    }
	ProTKFprintf(fp, "-------------------------------------------------\n");
	ProTKFprintf(fp, "-------------------------------------------------\n");
	
    return PRO_TK_NO_ERROR;
}

#ifndef PT_PRODUCTS_BUILD
/*====================================================================*\
FUNCTION :  ProTestQuiltSurfVisAct
PURPOSE  : Visit function for ProQuiltSurfaceVisit
\*====================================================================*/
ProError ProTestQuiltSurfVisAct(
    ProSurface surface, 
    ProError err,
    ProAppData app_data)
{
    ProGeomitem geom_item;
    ProError status;
    TestAppdata *tmp_appdata = (TestAppdata*)app_data;

    status = ProSurfaceIdGet(surface, &geom_item.id);
    TEST_CALL_REPORT("ProSurfaceIdGet()", 
	    "ProTestQuiltSurfVisAct()", status, status!=PRO_TK_NO_ERROR);

    geom_item.type = ProSurfaceDatatypeGet();
    geom_item.owner = tmp_appdata->owner;

    status = ProTestGeomitemVisAct(&geom_item, err, tmp_appdata->fp);

    return (status);
}


/*====================================================================*\
FUNCTION :  ProTestQuiltVisAct
PURPOSE  :  Visit function for ProFeatgeomitemVisit 
\*====================================================================*/
ProError ProTestQuiltVisAct(
    ProGeomitem *p_geom_item, 
    ProError err, 
    FILE *fp)
{
    ProError status;
    ProQuilt quilt;
    TestAppdata t_appdata;
    ProSurface *surfaces;
    int surfaces_num, i;

    ProTKFprintf(fp, "Doing quilt! Visiting quilt surfaces\n");
    status = ProQuiltInit((ProSolid)p_geom_item->owner, p_geom_item->id, &quilt);
    TEST_CALL_REPORT("ProQuiltInit()", 
	"ProTestQuiltVisAct()", status, status!=PRO_TK_NO_ERROR);

    status = ProQuiltToGeomitem((ProSolid)p_geom_item->owner, quilt, p_geom_item);
    TEST_CALL_REPORT("ProQuiltToGeomitem()", 
	"ProTestQuiltVisAct()", status, status!=PRO_TK_NO_ERROR);

    status = ProGeomitemToQuilt(p_geom_item, &quilt);
    TEST_CALL_REPORT("ProGeomitemToQuilt()", 
	"ProTestQuiltVisAct()", status, status!=PRO_TK_NO_ERROR);

    t_appdata.owner = p_geom_item->owner;
    t_appdata.fp = fp;
	
    status = ProUtilCollectQuiltSurfaces (quilt, &surfaces);
    if (status == PRO_TK_NO_ERROR)
    {
        status = ProArraySizeGet ((ProArray)surfaces, &surfaces_num);
        TEST_CALL_REPORT( "ProArraySizeGet()", "ProTestQuiltVisAct()", 
            status, status != PRO_TK_NO_ERROR );
        for (i = 0; i < surfaces_num; i++)
        {
            status = ProTestQuiltSurfVisAct (surfaces[i],
	        PRO_TK_NO_ERROR, (ProAppData)&t_appdata);
        }
        status = ProArrayFree ((ProArray*)&surfaces);
        TEST_CALL_REPORT( "ProArrayFree()", "ProTestQuiltVisAct()", 
            status, status != PRO_TK_NO_ERROR );
    }
    return (status);
}

#endif /* #ifndef PT_PRODUCTS_BUILD */

/*====================================================================*\
FUNCTION : ProTestGeomitemVisAct
PURPOSE  : 
\*====================================================================*/
ProError ProTestGeomitemVisAct ( 
    ProGeomitem *p_geom_item, 
    ProError err, 
    FILE *fp)
{
    ProError status;
    ProFeature  parent;
    ProSelection selection;
    ProCharName type_str;

    status = ProGeomitemFeatureGet(p_geom_item, &parent);
    TEST_CALL_REPORT("ProGeomitemFeatureGet()", 
	    "ProTestGeomitemVisAct()", status, status!=PRO_TK_NO_ERROR);
	    
    status = ProSelectionAlloc(NULL, &parent, &selection);
    TEST_CALL_REPORT("ProSelectionAlloc()", 
	    "ProTestGeomitemVisAct()", status, status!=PRO_TK_NO_ERROR);

    status = ProSelectionHighlight(selection, CYAN);

    ProUtilObjtypeStr(p_geom_item->type, type_str);

    ProTKFprintf(fp, "Visiting %s id %d. Parent feature is %d\n", 
	type_str, p_geom_item->id, parent.id);

    status = ProSelectionUnhighlight(selection);
    
    status = ProSelectionFree(&selection);
    TEST_CALL_REPORT("ProSelectionFree()", 
	    "ProTestGeomitemVisAct()", status, status!=PRO_TK_NO_ERROR);

    return PRO_TK_NO_ERROR;
}


/*====================================================================*\
FUNCTION : ProTestNameGen
PURPOSE  : Generate a uniqe model item name
\*====================================================================*/
ProError ProTestNameGen(ProType type, wchar_t *new_name)   
{
    ProError status = PRO_TK_BAD_INPUTS;
    char new_string[PRO_NAME_SIZE];
    int i;
    
    for (i=0; i < table_size; i++)
    {
	if (lookup_table[i].feat_type == type)
	{
	    ProTKSprintf(new_string, "%s%04d",lookup_table[i].name_pref,
		suff_num++);
	    ProStringToWstring(new_name, new_string);
	    status = PRO_TK_NO_ERROR;
	    break;
	}
    }
	
    return status;
}


/*====================================================================*\
FUNCTION : ProTestMdlNameGet
PURPOSE  : Retrieves the name of the selected model
\*====================================================================*/
int ProTestMdlNameGet(FILE *fp)
{
    ProError status;
    wchar_t wname[PRO_MDLNAME_SIZE];
    char    name[PRO_MDLNAME_SIZE];
    ProSelection *sels = NULL;
    int num;
    char option[] = "part";
    ProMdl model;
    ProModelitem model_item;

    status = ProSelect(option, 1, NULL, NULL, NULL, NULL, &sels, &num);
    TEST_CALL_REPORT("ProSelect()", "ProTestMdlNameGet()", status, status!=PRO_TK_NO_ERROR);

    if (status != PRO_TK_NO_ERROR || sels == NULL)
       return status;
    
    status = ProSelectionModelitemGet(sels[0], &model_item); 
    TEST_CALL_REPORT("ProSelectionModelitemGet()", 
	    "ProTestMdlNameGet()", status, status!=PRO_TK_NO_ERROR);

    status = ProModelitemMdlGet(&model_item, &model); 
    TEST_CALL_REPORT("ProSelectionModelitemGet()", 
	    "ProTestMdlNameGet()", status, status!=PRO_TK_NO_ERROR);

    status = ProMdlMdlnameGet(model, wname); 
    TEST_CALL_REPORT("ProMdlMdlnameGet()", 
	    "ProTestMdlNameGet()", status, status!=PRO_TK_NO_ERROR);

    ProTKFprintf(fp, "Selected model name        : %s\n",
	status != PRO_TK_NO_ERROR ? "Unknown" : ProWstringToString(name, wname));

    return status; 
}

/*====================================================================*\
FUNCTION : ProTestCustomFileOpen
PURPOSE  : Registers the specified type for opening.
\*====================================================================*/
ProError ProTestCustomFileOpen()
{
	ProError status;
        char ftype[] = "samp";
	char fdesc[] = "CustSampUsrDefFType";
	ProName w_ftype;
	ProName w_fdesc;

	ProStringToWstring(w_ftype, ftype);
	ProStringToWstring(w_fdesc, fdesc);

	status = ProFileOpenRegister(w_ftype, w_fdesc, (ProFileOpenAccessFunction)PTTestOpenAccessFunction,
						(ProFileOpenOperationAction)PTTestOpenOperationAction, NULL );
        TEST_CALL_REPORT("ProFileOpenRegister()", "ProTestCustomFileOpen()", status, status!=PRO_TK_NO_ERROR);                                                
        ProUtilMsgPrint ("gen", "TEST %0s", "The new type registered successfully.");
        
        return (status);
}

/*====================================================================*\
FUNCTION : ProTestCustomFileSave
PURPOSE  : Registers the specified type for saving.
\*====================================================================*/
ProError ProTestCustomFileSave()
{
	ProError status;
        char ftype[] = "samp";
	char fdesc[] = "CustSampUsrDefFType";
	ProName w_ftype;
	ProName w_fdesc;

	ProStringToWstring(w_ftype, ftype);
	ProStringToWstring(w_fdesc, fdesc);
		
	status = ProFileSaveRegister(w_ftype, w_fdesc, (ProFileSaveAccessFunction)PTTestSaveAccessFunction,
						(ProFileSaveOperationAction)PTTestSaveOperationAction, NULL); 
        TEST_CALL_REPORT("ProFileSaveRegister()", "ProTestCustomFileSave()", status, status!=PRO_TK_NO_ERROR);
        ProUtilMsgPrint ("gen", "TEST %0s", "The new type registered successfully.");
                                                      
        return (status);

}

/*====================================================================*\
FUNCTION : PTTestOpenAccessFunction
PURPOSE  : Callback function to select the file type in the file-open dialog box.
\*====================================================================*/
ProBoolean PTTestOpenAccessFunction (wchar_t* file_type, ProAppData app_data )  
{
         ProUtilMsgPrint ("gen", "TEST %0s", "The type registered successfully for opening.");
		
       	 return (PRO_B_TRUE);  
}
                                    
/*====================================================================*\
FUNCTION : PTTestOpenOperationAction
PURPOSE  : Callback action on pressing open button for new registered type.
\*====================================================================*/
ProError PTTestOpenOperationAction (wchar_t* file_type, ProPath file_path, ProAppData app_data )
{
        ProError status;
        
        status = ProSampCustomFileOpen();              
	TEST_CALL_REPORT ("ProSampCustomFileOpen()", "PTTestOpenAccessFunction", status, status != PRO_TK_NO_ERROR);

        ProUtilMsgPrint ("gen", "TEST %0s", "The operation performed successfully.");

  	return (PRO_TK_NO_ERROR);  
}

/*====================================================================*\
FUNCTION : PTTestSaveAccessFunction
PURPOSE  : Callback function to select the file type in the file-save a copy dialog box.
\*====================================================================*/
ProBoolean PTTestSaveAccessFunction (wchar_t* file_type, ProMdl model,  ProAppData app_data )
{         
        ProUtilMsgPrint ("gen", "TEST %0s", "The type  registered successfully for saving.");
       		
      	return (PRO_B_TRUE);  
}                          

/*====================================================================*\
FUNCTION : PTTestSaveOperationAction
PURPOSE  : Callback action on pressing ok button in save a copy for new registered type.
\*====================================================================*/
ProError PTTestSaveOperationAction (wchar_t* file_type, ProMdl model, ProPath file_path, ProAppData app_data )
{

        ProError status;
        char filename[PRO_PATH_SIZE];
        FILE *fp;

	status = ProMdlCurrentGet(&model);
        TEST_CALL_REPORT ("ProMdlCurrentGet()" ,"PTTestSaveOperationAction()", status, status != PRO_TK_NO_ERROR);

        ProTestQcrName (&model, (char*)".samp", filename);  
        fp = PTApplsUnicodeFopen (filename, "w");
                
        status = ProMdlSave(model);
        TEST_CALL_REPORT ("ProMdlSave()" ,"PTTestSaveOperationAction()", status, status != PRO_TK_NO_ERROR);
        
        ProUtilMsgPrint ("gen", "TEST %0s", "The model saved successfully.");
		
	return (PRO_TK_NO_ERROR);  
}

/*====================================================================*\
FUNCTION : ProSampCustomFileOpen
PURPOSE  : Function called in the callback function with specified type for open operation.
\*====================================================================*/
ProError ProSampCustomFileOpen()
{
    ProError status;
    char str[500];
    ProMdl model, mdl_handle;
    ProMdlName m_name;
    char filename[PRO_PATH_SIZE];
    ProPath name;
    ProFeature *feature;
    FILE *fp;
    ProMdlType type;
    int i = 0, data = 0;
    ProTestFeatData appdata;
                   
	status = ProNotificationSet(PRO_FILE_OPEN_OK, (ProFunction)ProOpenOk);
        TEST_CALL_REPORT ("ProNotificationSet()" ,"ProSampCustomFileOpen()", status, status != PRO_TK_NO_ERROR);
        
	sprintf(str, "ProNotificationSet : %d\n",(int)status);
/*--------------------------------------------------------------------------------*\
	Prompts to open the selected model using Open dialog box.
\*--------------------------------------------------------------------------------*/
        status = ProMdlCurrentGet(&model);  
        TEST_CALL_REPORT ("ProMdlCurrentGet()" ,"ProSampCustomFileOpen()", status, status != PRO_TK_NO_ERROR);

        status = ProMdlTypeGet(model, &type);  
        TEST_CALL_REPORT ("ProMdlTypeGet()" ,"ProSampCustomFileOpen()", status, status != PRO_TK_NO_ERROR);
            
        status = ProMdlnameInit(m_name, (ProMdlfileType)type, &mdl_handle);
        TEST_CALL_REPORT ("(ProMdlnameInit)" ,"ProSampCustomFileOpen()", status, status != PRO_TK_NO_ERROR);
       
        ProTestQcrName (&model, (char*)".samp", filename);  
        fp = PTApplsUnicodeFopen (filename, "w");
        appdata.data = fp;   
          if (fp == NULL)
            return (PRO_TK_GENERAL_ERROR);  
/*-------------------------------------------------------------------------------*\
	Collect all the features into an array from the current model 
\*-------------------------------------------------------------------------------*/  
           
        status = ProUtilCollectSolidFeatures((ProSolid)model, &feature); 
        TEST_CALL_REPORT ("ProUtilCollectSolidFeatures()" ,"ProSampCustomFileOpen()", status, status != PRO_TK_NO_ERROR);
       
        ProTKFprintf(fp,"--------------- User defined file type info --------------\n"); 
        status = ProTestFeatureInfoAct (&feature[i], PRO_TK_NO_ERROR, (ProAppData)&appdata);  
        TEST_CALL_REPORT ("ProTestFeatureInfoAct()" ,"ProSampCustomFileOpen()", status, status != PRO_TK_NO_ERROR);

        status = ProArrayFree((ProArray*)&feature);            
        fclose(fp);             
        ProStringToWstring (name, filename);  
/*------------------------------------------------------------------------------*\
	Display the information window
\*------------------------------------------------------------------------------*/           
        status = ProInfoWindowDisplay( name, NULL, NULL);
        TEST_CALL_REPORT ("ProInfoWindowDisplay()" ,"ProSampCustomFileOpen()", status, status != PRO_TK_NO_ERROR);
         
           return PRO_TK_NO_ERROR;       
}

ProError ProOpenOk(ProMdlType mdl_type, int sub_type, ProName model_name)
{
        return PRO_TK_NO_ERROR;
}
/*====================================================================*\
    FUNCTION :	ProTestFeatureInfoAct()
    PURPOSE  :	Generalized action function for visiting features
\*====================================================================*/
ProError ProTestFeatureInfoAct(
    ProModelitem *feature,
    ProError instatus,
    ProAppData appdata)
{
    ProError status;
    int action;
    FILE *fp;
    ProFeattype ftype;
    char ftype_str[PRO_NAME_SIZE];
    ProBoolean visible, geomchk, read_on;
    ProFeatStatus stat;

/*--------------------------------------------------------------------*\
    Get the action type and file pointer.
\*--------------------------------------------------------------------*/
    action = ((ProTestFeatData*)appdata)->action;
    fp = (FILE*)((ProTestFeatData*)appdata)->data;

    feature_number++;

/*--------------------------------------------------------------------*\
    Get the feature type
\*--------------------------------------------------------------------*/
    status = ProFeatureTypeGet(feature, &ftype);
    TEST_CALL_REPORT("ProFeatureTypeGet()", "ProTestFeatureInfoAct()",
				    status, status != PRO_TK_NO_ERROR);
    ProUtilFeattypeStr(ftype, ftype_str);

/*--------------------------------------------------------------------*\
    Get the feature visibility
\*--------------------------------------------------------------------*/
    status = ProFeatureVisibilityGet(feature, &visible);
    TEST_CALL_REPORT("ProFeatureVisibilityGet()", "ProTestFeatureInfoAct()",
					status, status != PRO_TK_NO_ERROR);

    status = ProFeatureHasGeomchks(feature, &geomchk);
    TEST_CALL_REPORT("ProFeatureHasGeomchks()", "ProTestFeatureInfoAct()",
					status, status != PRO_TK_NO_ERROR);

    status = ProFeatureIsReadonly(feature, &read_on);
    TEST_CALL_REPORT("ProFeatureIsReadonly()", "ProTestFeatureInfoAct()",
					status, status != PRO_TK_NO_ERROR);

    if(action == FEAT_LIST)
    {
/*--------------------------------------------------------------------*\
	Report the feature id, type and visibility as a list entry
\*--------------------------------------------------------------------*/
	ProTKFprintf(fp, "%-6d%-6d%-20s%-10s%-15s%-10s\n",
			feature_number, feature->id, ftype_str,
			visible == PRO_B_TRUE ? "" : "INTERNAL",
			geomchk == PRO_B_TRUE ? "Has geom cheks" : "",
			read_on == PRO_B_TRUE ? "Yes" : ""
			);
	return(PRO_TK_NO_ERROR);
    }
    else
    {
/*--------------------------------------------------------------------*\
	Report the feature id and type as a header 
\*--------------------------------------------------------------------*/
	ProTKFprintf(fp,"**********************************************************\n");
	if(visible == PRO_B_TRUE)
	    ProTKFprintf(fp,"USER FEATURE         %-d\n", feature_number);
	else
	    ProTKFprintf(fp,"INTERNAL FEATURE     %-d\n", feature_number);
	ProTKFprintf(fp,"INTERNAL ID          %-d\n", feature->id);
	ProTKFprintf(fp,"TYPE                 %s\n",  ftype_str);

/*--------------------------------------------------------------------*\
	Report everything else we know about the feature
\*--------------------------------------------------------------------*/
	ProUtilFeatureDump(feature, fp);

/*--------------------------------------------------------------------*\
	Report feature geometry
\*--------------------------------------------------------------------*/
        status = ProFeatureStatusGet(feature, &stat);
        TEST_CALL_REPORT("ProFeatureStatusGet()", "ProTestFeatureInfoAct()",
					status, status != PRO_TK_NO_ERROR);

	if ((ftype!=PRO_FEAT_COMPONENT)&&
            ((stat==PRO_FEAT_ACTIVE)||
             (stat==PRO_FEAT_UNREGENERATED)||
             (stat==PRO_FEAT_INACTIVE))) 
                ProTestFeatureInfoGeom(feature, fp); 
     }

    return(PRO_TK_NO_ERROR);
}
/*====================================================================*\
    FUNCTION :	ProTestFeatureInfoGeom()
    PURPOSE  :	Function for reporting feature geometry items
\*====================================================================*/
int ProTestFeatureInfoGeom(
    ProModelitem *feature,
    FILE *fp)
{
    ProError status;
    ProTestFeatData appdata;
    ProGeomitem	    *geomitems;
    int geomitems_num, i;

    appdata.data = fp;

    ProTKFprintf(fp, "Geometry items..\n");
    
    status = ProUtilCollectFeatureGeomitems (feature, PRO_TYPE_UNUSED, &geomitems);
    if (status == PRO_TK_NO_ERROR)
    {
        status = ProArraySizeGet ((ProArray)geomitems, &geomitems_num);
        for (i = 0; i < geomitems_num; i++)
        {
            status = ProTestGeomitemInfoAct (&geomitems[i],
	        PRO_TK_NO_ERROR, (ProAppData)&appdata);
        }
        status = ProArrayFree ((ProArray*)&geomitems);
        
    }
    return (0);
}

/*====================================================================*\
    FUNCTION :	ProTestGeomitemInfoAct()
    PURPOSE  :	Action function for visiting geometry items
\*====================================================================*/
ProError ProTestGeomitemInfoAct(
    ProGeomitem *item,
    ProError instatus,
    ProAppData appdata)
{
    FILE *fp;
    char item_type[PRO_NAME_SIZE];

    fp = (FILE*)((ProTestFeatData*)appdata)->data;

/*--------------------------------------------------------------------*\
    Report the type and id
\*--------------------------------------------------------------------*/
    ProUtilObjtypeStr(item->type, item_type);
    ProTKFprintf(fp,"    %-15s %2d\n", item_type, item->id);

    return(PRO_TK_NO_ERROR);
}