/*====================================================================*\
PURPOSE : Test functions uncovered by other tests

HISTORY..
DATE      BUILD   AUTHOR   MODIFICATIONS
10-Jul-96 G-03-19 mgs      $$1 Created
26-Aug-96 H-01-05 Xuekai   $$2 Modify due to change to ProMdl, etc.
05-Sep-96 H-01-07 Xuekai   $$3 Modify due to change to visit functions
09-Sep-96 H-01-08 Xuekai   $$4 obsolete protk.h, Pro*listFree=>ProArrayFree
12-Sep-96 H-01-09 Xuekai   $$5 Modify due to Pro[Point,Axis] => Opaque
24-Sep-96 H-01-10 Xuekai   $$6 Pro[Surface,Curve] => Opaque
25-Sep-96 H-01-10 Xuekai   $$7 Type casting opaque pointers
02-Oct-96 H-01-11 mgs	   $$8 Changes due to ProSelect
03-Oct-96 H-01-11 mgs	   $$9 Bug fix
08-Oct-96 H-01-12 amin	   $$10 Futher changes due to ProSelect
23-Oct-96 H-01-15 amin     $$11 ProGeomitemVisibiltyGet -> ProGeomitemIsActive
                                ProSelect arg list change
17-Nov-96 H-01-17 amin     $$12 ProGeomitemIsActive => ProGeomitemIsInactive()
07-Nov-96 H-01-20 amin     $$13 ProEdgeTessellationGet
16-Dec-96 H-01-21 mgs      $$14 Change test log macro
19-Jan-97 H-01-21 Pavel	   $$15 Added some function
05-Feb-97 H-01-25 Pavel    $$16 Added stuff_num++, removed ProEdgeVertexdataGet
				from ProTestGeomitemVisAct, 
				changed ProTestVisibilityFilt
28-Mar-97 H-01-30 Pavel   $$17 Added support for PT/Products Toolkit
			        Removed ProTestVisibilityFilt
17-Jun-97 H-01-15 Pavel   $$18 Removed ProContour functions, added new tests,
			       fixed ProTestMdlDelete
15-Sep-97 H-03-22 Pavel   $$19 Replace Pro/D on Pro/T
06-Oct-97 H-03-25 Pavel	  $$20 Reduced number of warnings
17-Oct-97 H-03-27 Pavel   $$21 Replaced Visit functions by UtilCollect
01-Jul-98 I-01-13 AKH     $$22 More support for PT/Products Toolkit
27-Nov-98 I-01-27 Pavel	  $$23 Removed code, duplicated in TestGeom.c
31-May-99 I-03-11 mka     $$24 Delete unused variable
\*====================================================================*/

/*--------------------------------------------------------------------*\
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"

/*--------------------------------------------------------------------*\
Application macros
\*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*\
Application data types
\*--------------------------------------------------------------------*/
typedef struct {    /* added due to change to ProQuilt */
    ProMdl owner;
    FILE *fp;
} TestAppdata;

typedef struct {
    ProFeattype feat_type;
    ProType     geom_type;
    char        name_pref[10];
} 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;

/*====================================================================*\
FUNCTION : ProTestMisc
PURPOSE  : 
\*====================================================================*/
int ProTestMisc(ProSolid* p_solid)
{
    ProError status;
    ProMdl   model;
    MafpInfo mafpinf;
    int      id;


    if ((mafpinf.fp = fopen("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("tk_misc", "tk_misc.mnu", &id);
    TEST_CALL_REPORT ("ProMenuFileRegister", "ProTestMiscMenu",
        status, status != PRO_TK_NO_ERROR);
    status = ProMenubuttonActionSet("tk_misc","-Init Test",
	(ProMenubuttonAction)ProTestFuncInit, (void *) &mafpinf,0);
    TEST_CALL_REPORT ("ProMenubuttonActionSet", "ProTestMiscMenu",
        status, status != PRO_TK_NO_ERROR);
    status = ProMenubuttonActionSet("tk_misc","-Name Get",
	(ProMenubuttonAction)ProTestMdlNameGet, (void *) mafpinf.fp,0);
    TEST_CALL_REPORT ("ProMenubuttonActionSet", "ProTestMiscMenu",
        status, status != PRO_TK_NO_ERROR);
    status = ProMenubuttonActionSet("tk_misc","tk_misc",
	(ProMenubuttonAction)ProTestMiscFpClose, (void *) mafpinf.fp,0);
    TEST_CALL_REPORT ("ProMenubuttonActionSet", "ProTestMiscMenu",
        status, status != PRO_TK_NO_ERROR);

    status = ProMenuCreate(PROMENUTYPE_MAIN,"tk_misc", &id);
    TEST_CALL_REPORT ("ProMenuCreate", "ProTestMiscMenu",
        status, status != PRO_TK_NO_ERROR);
    status = ProMenuProcess("tk_misk", &id);
    TEST_CALL_REPORT ("ProMenuProcess", "ProTestMiscMenu",
        status, status != PRO_TK_NO_ERROR);
    fclose(mafpinf.fp);
    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(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();
/*--------------------------------------------------------------------*\
    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)
    {
	fprintf(fp, "Feature Name before rename : %s\n", 
				    ProWstringToString(name, feat_name));
	status = ProTestNameGen(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);
	    fprintf(fp, "Feature Name after rename  : %s\n", 
					ProWstringToString(name, feat_name));
	}
    }
    else
    {
	fprintf(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)
	{
	    fprintf(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 )
    {
	fprintf(fp, "Feature skipped\n");
	fprintf(fp, "Feature skipped\n");
    }
	fprintf(fp, "-------------------------------------------------\n");
	fprintf(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 = 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;

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

    status = ProQuiltToGeomitem(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);

    fprintf(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)
	{
	    sprintf(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_NAME_SIZE];
    char    name[PRO_NAME_SIZE];
    ProSelection *sels;
    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);
    
    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 = ProMdlNameGet(model, wname); 
    TEST_CALL_REPORT("ProMdlNameGet()", 
	    "ProTestMdlNameGet()", status, status!=PRO_TK_NO_ERROR);

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

    return status; 
}
