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


/*--------------------------------------------------------------------*\
Pro/DEVELOP includes
\*--------------------------------------------------------------------*/

/*--------------------------------------------------------------------*\
Pro/TOOLKIT includes
\*--------------------------------------------------------------------*/
#include <ProToolkit.h>
#include <ProMdl.h>
#include <ProMenu.h>
#include <ProSolid.h>
#include <ProXsec.h>
#include <ProSelection.h>
#include <ProSurface.h>
#include <ProUtil.h>
#include <UtilMenu.h>

/*--------------------------------------------------------------------*\
Application includes
\*--------------------------------------------------------------------*/
#include "TestXsec.h"
#include "TestError.h"
#include <UtilMessage.h>
#include <ProMessage.h>
#include <ProQuilt.h>
#include <UtilCollect.h>
#include <PTApplsUnicodeUtils.h>
#include <UtilCollect.h>
#include <ProModelitem.h>
#include <UtilString.h>
#include <ProTKRunTime.h>
/*--------------------------------------------------------------------*\
Application macros
\*--------------------------------------------------------------------*/

#define PRO_TEST_XSEC_MODIFY_DIMVALUES  1
#define PRO_TEST_XSEC_MODIFY_REDEFINE   2
#define PRO_TEST_XSEC_MODIFY_HATCHING   3
#define PRO_TEST_XSEC_MODIFY_NAME       4
/*--------------------------------------------------------------------*\
Application data types
\*--------------------------------------------------------------------*/

/*--------------------------------------------------------------------*\
Application global/external data
\*--------------------------------------------------------------------*/

/*====================================================================*\
    FUNCTION :	ProTestXsec
    PURPOSE  :	Menu for section action            
\*====================================================================*/
int ProTestXsec (
    ProSolid *p_model)
{
    int id;
    ProError status;
    status = ProMenuFileRegister((char*)"TkXsec",(char*)"tkxsec.mnu", &id);
    TEST_CALL_REPORT ("ProMenuFileRegister", "ProTestXsecMenu",
        status, status != PRO_TK_NO_ERROR);
        
    status = ProMenubuttonActionSet((char*)"TkXsec",(char*)"-Create",
        (ProMenubuttonAction)ProTestXsecCreate, p_model, 0);
    TEST_CALL_REPORT ("ProMenubuttonActionSet", "ProTestXsecMenu",
        status, status != PRO_TK_NO_ERROR);
    status = ProMenubuttonActionSet((char*)"TkXsec",(char*)"-Delete",
        (ProMenubuttonAction)ProTestXsecDelete, p_model, 0);
    TEST_CALL_REPORT ("ProMenubuttonActionSet", "ProTestXsecMenu",
        status, status != PRO_TK_NO_ERROR);
    status = ProMenubuttonActionSet((char*)"TkXsec",(char*)"-Show",
        (ProMenubuttonAction)ProTestXsecShow, p_model, 0);
    TEST_CALL_REPORT ("ProMenubuttonActionSet", "ProTestXsecMenu",
        status, status != PRO_TK_NO_ERROR);
    status = ProMenubuttonActionSet((char*)"TkXsec",(char*)"-Erase",
        (ProMenubuttonAction)ProTestNotSupported, p_model,0);
    TEST_CALL_REPORT ("ProMenubuttonActionSet", "ProTestXsecMenu",
        status, status != PRO_TK_NO_ERROR);
    status = ProMenubuttonActionSet((char*)"TkXsec",(char*)"-Copy",
        (ProMenubuttonAction)ProTestNotSupported, p_model,0);
    TEST_CALL_REPORT ("ProMenubuttonActionSet", "ProTestXsecMenu",
        status, status != PRO_TK_NO_ERROR);
    status = ProMenubuttonActionSet((char*)"TkXsec",(char*)"-Modify",
        (ProMenubuttonAction)ProTestXsecModify, p_model,0);
    TEST_CALL_REPORT ("ProMenubuttonActionSet", "ProTestXsecMenu",
        status, status != PRO_TK_NO_ERROR);
    status = ProMenubuttonActionSet((char*)"TkXsec",(char*)"-ListAllParams",
        (ProMenubuttonAction)ProTestXsecListAllParams, p_model,0);
    TEST_CALL_REPORT ("ProMenubuttonActionSet", "ProTestXsecMenu",
        status, status != PRO_TK_NO_ERROR);    
    status = ProMenubuttonActionSet((char*)"TkXsec",(char*)"TkXsec",
        (ProMenubuttonAction)ProMenuDelete, NULL,0);
    TEST_CALL_REPORT ("ProMenubuttonActionSet", "ProTestXsecMenu",
        status, status != PRO_TK_NO_ERROR);    


    status = ProMenuCreate(PROMENUTYPE_MAIN,(char*)"TkXsec", &id);
    TEST_CALL_REPORT ("ProMenuCreate", "ProTestXsecMenu",
        status, status != PRO_TK_NO_ERROR);
    status = ProMenuProcess((char*)"TkXsec", &id);
    TEST_CALL_REPORT ("ProMenuProcess", "ProTestXsecMenu",
        status, status != PRO_TK_NO_ERROR);

    return(PRO_TK_NO_ERROR);
}

/*====================================================================*\
    FUNCTION :	ProTestNotSupported
    PURPOSE  :	            
\*====================================================================*/
int ProTestNotSupported (ProAppData app_data, int app_int)
{
    ProUtilMsgPrint("gen","TEST %0s","Function not supported.");
    return (PRO_TK_NO_ERROR);
}

/*====================================================================*\
    FUNCTION :	ProTestXsecCreate
    PURPOSE  :	Creates a cross section through a datum plane.            
\*====================================================================*/
int ProTestXsecCreate (
    ProSolid    *p_model)
{
    int             sel_num, plane_id, quilt_id;
    ProXsecCutobj   xsec_type;
    ProSolid        solid_owner = *p_model;
    ProName         w_name;
    ProError        status;
    ProSelection    *sel_array = NULL;
    ProModelitem    model_item;
    ProSurface      surface;
    ProSrftype      surface_type;
    ProXsec         xsec;
    ProQuilt	    quilt;

    
    ProUtilMsgPrint ("gen", "TEST %0s", "Enter name of new cross section:");
    
    if (ProMessageStringRead (PRO_NAME_SIZE, w_name) != PRO_TK_NO_ERROR)
        return (PRO_TK_NO_ERROR);

    while (1==1)
    {
    	ProUtilMsgPrint ("gen", "TEST %0s", "Select plane through which the cross "
                                        "section will be created");

        status = ProSelect ((char*)"datum,surface", 1, NULL, NULL, NULL, NULL,
            &sel_array, &sel_num);
        TEST_CALL_REPORT ("ProSelect", "ProTestXsecCreate",
            status, status != PRO_TK_NO_ERROR);
        
        if (status == PRO_TK_USER_ABORT || status == PRO_TK_PICK_ABOVE)
            return (PRO_TK_NO_ERROR);
   
        status = ProSelectionModelitemGet (sel_array[0], &model_item);
        TEST_CALL_REPORT ("ProSelectionModelItemGet", "ProTestXsecCreate",
            status, status != PRO_TK_NO_ERROR);

        status = ProGeomitemToSurface ((ProGeomitem*)&model_item, &surface);
        TEST_CALL_REPORT ("ProGeomitemToSurface", "ProTestXsecCreate",
            status, status != PRO_TK_NO_ERROR);

        status = ProSurfaceTypeGet (surface, &surface_type);
        TEST_CALL_REPORT ("ProSurfaceTypeGet", "ProTestXsecCreate",
            status, status != PRO_TK_NO_ERROR);
            
        if (surface_type == PRO_SRF_PLANE)
        {
	    status = ProSurfaceIdGet (surface, &plane_id);
    	    TEST_CALL_REPORT ("ProSurfaceIdGet","ProTestXsecCreate",
    	    	status, status != PRO_TK_NO_ERROR);

            break;
	}

    	ProUtilMsgPrint ("gen", "TEST %0s", "Its not plane surface."
    	    	    	    	"Try again.");
    }

    xsec_type = (ProXsecCutobj)ProTestXsecTypeMenu ();
    if ((int)xsec_type == -1)
        return (PRO_TK_GENERAL_ERROR);

    if (xsec_type == PRO_XSECTYPE_QUILTS)
    {
    	ProUtilMsgPrint ("gen", "TEST %0s", "Select quilt for cut.");

        status = ProSelect ((char*)"dtmqlt", 1, NULL, NULL, NULL, NULL,
            &sel_array, &sel_num);
        TEST_CALL_REPORT ("ProSelect", "ProTestXsecCreate",
            status, status != PRO_TK_NO_ERROR);

        if (status == PRO_TK_USER_ABORT || status == PRO_TK_PICK_ABOVE)
            return (PRO_TK_NO_ERROR);

        status = ProSelectionModelitemGet (sel_array[0], &model_item);
        TEST_CALL_REPORT ("ProSelectionModelItemGet", "ProTestXsecCreate",
            status, status != PRO_TK_NO_ERROR);

        status = ProGeomitemToQuilt ((ProGeomitem*)&model_item, &quilt);
    	TEST_CALL_REPORT ("ProGeomitemToQuild", "ProTestXsecCreate",
    	    status, status != PRO_TK_NO_ERROR);
    
    	status = ProQuiltIdGet (quilt, &quilt_id);
    	TEST_CALL_REPORT ("ProQuiltIdGet", "ProTestXsecCreate",
    	    status, status != PRO_TK_NO_ERROR);
    }
    else
        quilt_id = -1;

    status = ProXsecPlanarWithoptionsCreate (solid_owner, w_name,
        plane_id, xsec_type, NULL, quilt_id, 1, PRO_XSEC_MODEL_EXCLUDE, NULL, &xsec );
    TEST_CALL_REPORT ("ProXsecPlanarWithoptionsCreate", "ProTestXsecCreate",
        status, status != PRO_TK_NO_ERROR);
	
    if (status != PRO_TK_NO_ERROR)
    	return status;

    status = ProXsecDisplay( &xsec);
    TEST_CALL_REPORT ("ProXsecDisplay", "ProTestXsecCreate",
        status, status != PRO_TK_NO_ERROR);
    return (PRO_TK_NO_ERROR);
}

/*====================================================================*\
    FUNCTION :	ProTestXsecTypeMenu
    PURPOSE  :	.            
\*====================================================================*/
int ProTestXsecTypeMenu ()
{
    int id;

    ProUtilMenuButtons  buttons[] = {
            {"TkXsecType", -1, TEST_CALL_PRO_MENU_DELETE},
                {"TypeModel", PRO_XSECTYPE_MODEL, 0},
                {"TypeQuilts", PRO_XSECTYPE_QUILTS, 0},
                {"TypeModelQuilts", PRO_XSECTYPE_MODELQUILTS, 0},
                {"", -1, 0}};
                
    if (ProUtilMenuIntValueSelect( buttons, &id) != PRO_TK_NO_ERROR)
        return -1;

    return id;
}

/*====================================================================*\
    FUNCTION :	ProTestXsecDelete
    PURPOSE  :	.            
\*====================================================================*/
int  ProTestXsecDelete (
    ProSolid *p_solid)
{
    ProXsec     xsec;
    ProError    status;

    status = ProTestXsecSelect (*p_solid, &xsec);
    if (status == PRO_TK_NO_ERROR)
    {
        status = ProXsecDelete(&xsec);
        TEST_CALL_REPORT ("ProXsecDelete", "ProTestXsecDelete",
            status, status != PRO_TK_NO_ERROR);
        return (0);
    }
    return (-1);
}


/*====================================================================*\
    FUNCTION :	ProTestXsecShow
    PURPOSE  :	.            
\*====================================================================*/
int ProTestXsecShow (
    ProSolid *p_solid)
{
    ProXsec xsec;
    while (ProTestXsecSelect(*p_solid, &xsec) == PRO_TK_NO_ERROR);
    return (0);
}

/*====================================================================*\
    FUNCTION :	ProTestXsecModify
    PURPOSE  :	.            
\*====================================================================*/
int ProTestXsecModify (
    ProSolid *p_solid)
{
    int id;
    ProError status;
    ProUtilMenuButtons  buttons[] = {
            {"TkXsecModify", -1, 0},
                {"Dim Values", PRO_TEST_XSEC_MODIFY_DIMVALUES,
                    TEST_CALL_PRO_MENU_ACTIVATE},
                {"Redefine", PRO_TEST_XSEC_MODIFY_REDEFINE,
                    TEST_CALL_PRO_MENU_ACTIVATE},
                {"Hatching", PRO_TEST_XSEC_MODIFY_HATCHING,
                    TEST_CALL_PRO_MENU_ACTIVATE},
                {"Name", PRO_TEST_XSEC_MODIFY_NAME,
                    TEST_CALL_PRO_MENU_ACTIVATE},
                {"", -1, 0}};
    ProXsec xsec;
    ProName w_name;


    if (ProUtilMenuIntValueSelect( buttons, &id) != PRO_TK_NO_ERROR)
        return 0;
    
    if (ProTestXsecSelect(*p_solid, &xsec) != PRO_TK_NO_ERROR)
        return (0);

    switch (id)
    {
    case PRO_TEST_XSEC_MODIFY_DIMVALUES:
        ProTestNotSupported (NULL, 0);
        break;
    case PRO_TEST_XSEC_MODIFY_REDEFINE:
        ProTestNotSupported (NULL, 0);
        break;
    case PRO_TEST_XSEC_MODIFY_HATCHING:
        ProTestNotSupported (NULL, 0);
        break; 
    case PRO_TEST_XSEC_MODIFY_NAME:
        {
            ProUtilMsgPrint ("gen", "TEST %0s", "Enter new name:");

            if (ProMessageStringRead (PRO_NAME_SIZE, w_name) != PRO_TK_NO_ERROR)
                return (0);

            status = ProXsecRename( &xsec, w_name);
            TEST_CALL_REPORT ("ProXsecRename", "ProTestXsecModify",
                status, status != PRO_TK_NO_ERROR);
        }
        break;
    }
    
    /* bug 1334 */
    status = ProXsecRegenerate( &xsec );
    TEST_CALL_REPORT ("ProXsecRegenerate", "ProTestXsecModify",
        status, status != PRO_TK_NO_ERROR && status != PRO_TK_BAD_INPUTS);

    return (0);
}

/*====================================================================*\
    FUNCTION :	ProTestXsecSelect
    PURPOSE  :	.            
\*====================================================================*/
ProError ProTestXsecSelect (
    ProSolid    solid_owner,
    ProXsec *xsec_ptr)      /* Out: Selected Xsec, user's memory */
{
    int                 i, array_size;
    ProError            status;
    ProXsec             *xsec_array=NULL;
    wchar_t             **w_menu_buttons;

    
    status = ProMdlCurrentGet ((ProMdl*)&solid_owner);
    TEST_CALL_REPORT ("ProMdlCurrentGet", "ProTestXsecSelect",
        status, status != PRO_TK_NO_ERROR);

    status =  ProUtilCollectSolidXsec (solid_owner, &xsec_array);
    if (status != PRO_TK_NO_ERROR)
    {
        ProUtilMsgPrint ("gen", "TEST %0s", "Model don't have cross section:");
        return (PRO_TK_E_NOT_FOUND);
    }
    
    status = ProArraySizeGet ((ProArray)xsec_array, &array_size);
        
    ProUtilMenuStringsAlloc(&w_menu_buttons);

    for (i=0; i<array_size; i++)
        ProUtilMenuStringsWstrAdd(&w_menu_buttons, xsec_array[i].xsec_name);

    if (ProUtilMenuStringsIntValueSelect((char*)"TkXsecNames",  w_menu_buttons, &i) 
        == PRO_TK_NO_ERROR)
    {
        xsec_ptr[0] = xsec_array[i];
        
        status = ProXsecDisplay( xsec_ptr);
        TEST_CALL_REPORT ("ProXsecDisplay", "ProTestXsecSelect",
            status, status != PRO_TK_NO_ERROR);
    }
    else
        i = -1;
    
    ProUtilMenuStringsAlloc(&w_menu_buttons);
    
    status = ProArrayFree ((ProArray*)&xsec_array);
    
    return (i != -1)? PRO_TK_NO_ERROR : PRO_TK_GENERAL_ERROR;
}

/*====================================================================*\
    FUNCTION :	ProTestXsecListAllParams
    PURPOSE  :	.            
\*====================================================================*/
int ProTestXsecListAllParams (
    ProSolid *p_solid)
{
    int         i, j, array_size, n_geom, csys_selected = 0;
    FILE        *fp = NULL;
    char        c_name[PRO_NAME_SIZE];
    
    ProError	    status;
    ProName         w_name;
    ProXsecType     xsec_type;
    ProXsecGeom     *p_xsec_geom;
    ProMassProperty xsec_massproperty;
    ProSolid  	    solid_owner = *p_solid;   
    ProXsec     *xsec_array=NULL;

    status = ProUtilCollectSolidXsec (solid_owner, &xsec_array);
    if (status != PRO_TK_NO_ERROR)
    {
        ProUtilMsgPrint ("gen", "TEST %0s", "Model don't have cross section:");
        return (PRO_TK_E_NOT_FOUND);
    }
     
    status = ProArraySizeGet ((ProArray)xsec_array, &array_size);
    
    fp = PTApplsUnicodeFopen ("xsec_info.inf", "w");
    if (fp != NULL)
    {
        for (i=0; i<array_size; i++)
        {
            status = ProXsecTypeGet (&xsec_array[i], &xsec_type);
            TEST_CALL_REPORT ("ProXsecTypeGet",
                "ProTestXsecListAllParams", status, status != PRO_TK_NO_ERROR);

            ProWstringToString (c_name, xsec_array[i].xsec_name);
            ProTKFprintf (fp, "Cross section name %s, type %s,",
                        c_name, (xsec_type.cutter)? "offset" : "planar");
            switch (xsec_type.cut_object)
            {
                case PRO_XSECTYPE_MODEL:
                    strcpy (c_name, "model");
                    break;
                case PRO_XSECTYPE_QUILTS:
                    strcpy (c_name, "quilt");
                    break;
                case PRO_XSECTYPE_MODELQUILTS:
                    strcpy (c_name, "model_and_quilts");
                    break;
                default:
                    strcpy (c_name, "unknown");
            }
            ProTKFprintf (fp, " cut object %s.\n", c_name);

            status = ProXsecGeometryRetrieve (&xsec_array[i], &p_xsec_geom);
            TEST_CALL_REPORT ("ProXsecGeometryRetrieve",
                "ProTestXsecListAllParams", status, status != PRO_TK_NO_ERROR);

            status = ProArraySizeGet((ProArray)p_xsec_geom, &n_geom);
            for (j=0; j<n_geom; j++)
            {
                ProTKFprintf (fp, "Geometry %d\n", j+1);
    	    	ProTKFprintf (fp, "\tMemb id tab %d quilt id %d\n",
		    	    p_xsec_geom[j].memb_id_tab,
		    	    p_xsec_geom[j].quilt_id);
            }
            
            if (xsec_type.cutter != PRO_XSEC_OFFSET && 
                xsec_type.cut_object != PRO_XSECTYPE_QUILTS)
            {
                if (!csys_selected)
                {
                    if (ProTestXsecCsysSelect (solid_owner, w_name) == 0)
		            w_name[0] = '\0';
                    csys_selected = 1;
                    ProWstringToString(c_name, w_name);
                }
                
                /* Bug 1337 */           
                status = ProXsecMassPropertyCompute (&xsec_array[i],
		    	        w_name, &xsec_massproperty);
		TEST_CALL_REPORT ("ProXsecMassPropertyCompute",
		    "ProTestXsecListAllParams", status, 
                    status != PRO_TK_NO_ERROR && status != PRO_TK_BAD_INPUTS);
                ProTKFprintf(fp, "Mass properties in csys %s\n", c_name);
		ProTKFprintf (fp,
		        "\tSurface area %f; center of gravity (%.5f,%.5f).\n",
		    	xsec_massproperty.surface_area,
			xsec_massproperty.center_of_gravity[0],
			xsec_massproperty.center_of_gravity[1]);
		ProTKFprintf (fp, "\tCoord system in area:\n");
		ProTKFprintf (fp, "\t\t%.5f\t%.5f\n",
		        xsec_massproperty.coor_sys_inertia[0][0],
			xsec_massproperty.coor_sys_inertia[0][1]);
		ProTKFprintf (fp, "\t\t%.5f\t%.5f\n",
		    	xsec_massproperty.coor_sys_inertia[1][0],
			 xsec_massproperty.coor_sys_inertia[1][1]);
            }
	    ProTKFprintf (fp, "\n");

        }
        fclose(fp);
    }
    
    status = ProArrayFree ((ProArray*)&xsec_array);
    TEST_CALL_REPORT ("ProArrayFree", "ProTestXsecListAllParams",
        status, status != PRO_TK_NO_ERROR);
    return (0);
}

/*====================================================================*\
    FUNCTION :	ProTestXsecCsysSelect
    PURPOSE  :	.            
\*====================================================================*/
ProError ProTestXsecCsysSelect (
    ProSolid solid,
    ProName  w_csys_name)
{
    int     	    	i, array_size;
    ProError	    	status;
    ProCsys 	    	*csys_array = NULL;
    ProGeomitem 	geomitem;
    wchar_t             **w_menu_buttons;

    if (ProUtilCollectSolidCsys ( solid, &csys_array) != PRO_TK_NO_ERROR)
    	return (PRO_TK_E_NOT_FOUND);
		
    status = ProArraySizeGet ((ProArray)csys_array, &array_size);
    TEST_CALL_REPORT ("ProArrayFree", "ProArraySizeGet",
        status, status != PRO_TK_NO_ERROR);
 
    ProUtilMenuStringsAlloc(&w_menu_buttons);
    for (i=0; i<array_size; i++)
    {
    	status = ProCsysToGeomitem (solid, csys_array[i], &geomitem);
	TEST_CALL_REPORT ("ProCsysToGeomitem ", "ProTestXsecCsysSelect",
    	    status, status != PRO_TK_NO_ERROR);
	    
	status = ProModelitemNameGet ((ProModelitem*)&geomitem, w_csys_name);
	TEST_CALL_REPORT ("ProModelitemNameGet", "ProTestXsecCsysSelect",
    	    status, status != PRO_TK_NO_ERROR);

        ProUtilMenuStringsWstrAdd(&w_menu_buttons, w_csys_name);
    }
    status = ProUtilMenuStringsIntValueSelect((char*)"TkCsysNames",  w_menu_buttons,
        &i);  
    if ( status == PRO_TK_NO_ERROR)
        ProUtilWstrcpy(w_csys_name, w_menu_buttons[i]);
    else
    {
        i = -1;
        w_csys_name[0] = (wchar_t)'\0';
    }
    
    ProUtilMenuStringsFree(&w_menu_buttons);
    status = ProArrayFree ((ProArray*)&csys_array);
    
    return (i != -1)? PRO_TK_NO_ERROR : PRO_TK_GENERAL_ERROR;
}