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


/*--------------------------------------------------------------------*\
    Pro/TOOLKIT includes
\*--------------------------------------------------------------------*/
#include <ProObjects.h>
#include <ProPart.h>
#include <ProUtil.h>
#include <ProMaterial.h>
#include <ProMenu.h>
#include <ProWstring.h>
#include <ProMessage.h>
#include <ProTKRunTime.h>

/*--------------------------------------------------------------------*\
    Application includes
\*--------------------------------------------------------------------*/
#include "TestError.h"
#include "UtilMessage.h"
#include "UtilString.h"

/*--------------------------------------------------------------------*\
    Macros
\*--------------------------------------------------------------------*/
#define USER_ADD     0
#define USER_DELETE  1
#define USER_ASSIGN  2
#define USER_DENSITY 3
#define USER_READ    4
#define USER_WRITE   5

/*--------------------------------------------------------------------*\
    Application global/external data
\*--------------------------------------------------------------------*/
static struct pro_material_props def_props = {
 29e6, /*yonug_modulus*/
 0.27, /*poisson_ratio*/
 11e6,
 0.00879, /*mass_density*/
 6.78, 
 32.0, /*tharm_exp_ref_temp*/
 0.01, 
 36000.0, /*stress_lim_tension*/
 36000.0,
 36000.0, /*stress_lim_shear*/
 0.0,
 1.0, /*emisisivity*/
 1.0,
 1.0, /*hardness*/
 {0},
 0.0, /*init_bend_y_factor*/
 {0}
};

/*=============================================================*\
 Function: ProTestPartMaterial()
 Purpose:  Get/Set the part material name
\*=============================================================*/
int ProTestPartMaterial( ProMdl* part)
{
    int ProTestMaterialAction();
    int menu_id, action;

    ProMenuFileRegister((char*)"TkMaterial",(char*)"tkmaterial.mnu", NULL);
    ProMenubuttonActionSet((char*)"TkMaterial",(char*)"TkMaterial",
                           (ProMenubuttonAction)ProMenuDelete, NULL,  0);
    ProMenubuttonActionSet((char*)"TkMaterial",(char*)"-Done/Return",
                           (ProMenubuttonAction)ProMenuDelete, NULL,  0);
    ProMenubuttonActionSet((char*)"TkMaterial",(char*)"-Add",
               	(ProMenubuttonAction)ProTestMaterialAction, part, USER_ADD);
    ProMenubuttonActionSet((char*)"TkMaterial",(char*)"-Delete",
               	(ProMenubuttonAction)ProTestMaterialAction, part, USER_DELETE);
    ProMenubuttonActionSet((char*)"TkMaterial",(char*)"-Assign",
               	(ProMenubuttonAction)ProTestMaterialAction, part, USER_ASSIGN);
    ProMenubuttonActionSet((char*)"TkMaterial",(char*)"-Density",
               	(ProMenubuttonAction)ProTestMaterialAction, part, USER_DENSITY);
    ProMenubuttonActionSet((char*)"TkMaterial",(char*)"-Read",
               	(ProMenubuttonAction)ProTestMaterialAction, part, USER_READ);
    ProMenubuttonActionSet((char*)"TkMaterial",(char*)"-Write",
               	(ProMenubuttonAction)ProTestMaterialAction, part, USER_WRITE);
    
    ProMenuCreate(PROMENUTYPE_MAIN, (char*)"TkMaterial", &menu_id);
    ProMenuProcess((char*)"TkMaterial", &action);

    return 0;
}


/*=============================================================*\
 Function: ProUtilSelectMaterial()
 Purpose: select one material from part 
\*=============================================================*/
ProError ProUtilSelectMaterial(ProSolid *part, ProMaterial *material)
{
    ProError status, st;
    ProName * p_name, w_name;
    wchar_t empty = 0, **w_sel;
    ProWstring *w_array, p_empty; 
    int i, n_lines, n_sel;

    status = ProArrayAlloc(0, sizeof(ProName), 1, (ProArray*) &p_name);
    TEST_CALL_REPORT("ProArrayAlloc()", "ProUtilSelectMaterial()",
					    status,status != PRO_TK_NO_ERROR);
    status = ProPartMaterialsGet(*part, &p_name);
    TEST_CALL_REPORT("ProPartMaterialsGet()", "ProUtilSelectMaterial()",
					    status,status != PRO_TK_NO_ERROR);
    if (status != PRO_TK_NO_ERROR)
    {
	ProUtilMsgPrint((char*)"gen", (char*)"TEST %0s", (char*)"Unable select material");
    }
    else
    {
	status = ProArrayAlloc(0, sizeof(ProWstring), 1, (ProArray*)&w_array);
        TEST_CALL_REPORT("ProArrayAlloc()", "ProUtilSelectMaterial()",
					    status,status != PRO_TK_NO_ERROR);
	status = ProArraySizeGet((ProArray)p_name, &n_lines);
        TEST_CALL_REPORT("ProArraySizeGet()", "ProUtilSelectMaterial()",
					    status,status != PRO_TK_NO_ERROR);

	for (i=0; i<n_lines; i++)
	{
	    p_empty = p_name[i];
 	    status = ProWstringArrayObjectAdd(&w_array, PRO_VALUE_UNUSED, 
	    	1, (ProWstring*)&p_empty);
            TEST_CALL_REPORT("ProWstringArrayObjectAdd()", 
	    	"ProUtilSelectMaterial()", status, status != PRO_TK_NO_ERROR);
	}
	status = ProWstringArraySizeSet(&w_array, n_lines + 1);
        TEST_CALL_REPORT("ProWstringArraySizeSet()", 
	    "ProUtilSelectMaterial()", status, status != PRO_TK_NO_ERROR);
	p_empty = &empty;
	w_array[n_lines] = p_empty;
	ProStringToWstring(w_name, (char*)"Materials");
	ProUtilMsgPrint((char*)"gen", (char*)"TEST %0s", (char*)"Select material");
	st = ProMenuStringsSelect(w_name, w_array, 1, NULL, &w_sel, &n_sel);
	status = ProWstringArrayObjectRemove(&w_array, n_lines, 1);
        TEST_CALL_REPORT("ProWstringArrayObjectRemove()", 
	    "ProUtilSelectMaterial()", status, status != PRO_TK_NO_ERROR);
	status = ProWstringArrayFree(&w_array);
        TEST_CALL_REPORT("ProWstringArrayFree()", 
	    "ProUtilSelectMaterial()", status, status != PRO_TK_NO_ERROR);
	if (st == PRO_TK_NO_ERROR)
	{
	    ProUtilWstrcpy(material->matl_name, w_sel[0]);
	    material->part = *part; 
	}
	status = st;
    }
    st = ProArrayFree((ProArray*)&p_name);
    TEST_CALL_REPORT("ProArrayFree()", "ProUtilSelectMaterial()",
					status, status != PRO_TK_NO_ERROR);
    return (status);
}

/*=============================================================*\
 Function: ProTestMaterialAction()
 Purpose:  all material actions 
\*=============================================================*/
int ProTestMaterialAction(ProSolid *part, int action)
{
    static int current_get, data_get, current_set;
    ProMaterial material;
    ProName w_name;
    ProError status;
    ProMaterialdata mat_data;
    ProCharLine line;
    double drange[2] = {1e-3, 1e10}, dens;
    char name[PRO_NAME_SIZE];
	ProMaterialItem matItem;
	ProParamvalue    matValue;
	ProUnititem      matUnits;

    switch (action)
    {
    case USER_ADD:
	ProUtilMsgPrint((char*)"gen", (char*)"TEST %0s", (char*)"Enter new material name:");
	status = ProMessageStringRead(PRO_NAME_SIZE, w_name);
	if (status == PRO_TK_NO_ERROR)
	{
	    status = ProMaterialCreate(*part, w_name, &def_props, &material);
       	    TEST_CALL_REPORT("ProMaterialCreate()", "ProTestMaterialAction()",
                                        status, status != PRO_TK_NO_ERROR);
 	    if (status == PRO_TK_NO_ERROR)
		ProUtilMsgPrint((char*)"gen", (char*)"TEST %0s", 
					    "Material created successfully");
	}
	break;
    case USER_DELETE:
	status = ProUtilSelectMaterial(part, &material);
	if (status == PRO_TK_NO_ERROR)
	{
	    status = ProMaterialDelete(&material);
       	    TEST_CALL_REPORT("ProMaterialDelete()", "ProTestMaterialAction()",
                                        status, status != PRO_TK_NO_ERROR);
 	    if (status == PRO_TK_NO_ERROR)
		ProUtilMsgPrint((char*)"gen", (char*)"TEST %0s", 
					    "Material removed successfully");
	}
	break;
    case USER_ASSIGN:
	status = ProUtilSelectMaterial(part, &material);

	if (status != PRO_TK_NO_ERROR)
		break;
	if ((current_set++) & 1)
	  {
		status = ProMaterialCurrentSet(&material);
       	    	TEST_CALL_REPORT("ProMaterialCurrentSet()", 
		   "ProTestMaterialAction()",status,status != PRO_TK_NO_ERROR);

		 if (status == PRO_TK_NO_ERROR)	    
 	      ProUtilMsgPrint((char*)"gen", (char*)"TEST %0s", 
					    "Material assigned successfully");
	   }	    	
	break;
    case USER_DENSITY:
	if ((current_get++) & 1)
	{
	    status = ProMaterialCurrentGet(*part, &material);
       	    TEST_CALL_REPORT("ProMaterialCurrentGet()", 
	   	"ProTestMaterialAction()",status,status != PRO_TK_NO_ERROR);
   
		status = ProModelitemByNameInit(*part,PRO_RP_MATERIAL,material.matl_name,&matItem);
		TEST_CALL_REPORT( "ProModelitemByNameInit()", 
	    	"ProTestMaterialAction()",status, status != PRO_TK_NO_ERROR);

		status = ProMaterialPropertyGet(&matItem,PRO_MATPROP_MASS_DENSITY, &matValue,&matUnits);
		TEST_CALL_REPORT( "ProMaterialPropertyGet()", 
	    	"ProTestMaterialAction()",status, status != PRO_TK_NO_ERROR);
	
	}
	ProTKSprintf(line, (char*)"Enter new density value [%.3f]:",matValue.value.d_val);
	ProUtilMsgPrint((char*)"gen", (char*)"TEST %0s", line);
	status = ProMessageDoubleRead(drange, &dens);
	if (status == PRO_TK_NO_ERROR)
	   matValue.value.d_val = dens;

	status = ProMaterialPropertySet(&matItem,PRO_MATPROP_MASS_DENSITY, &matValue,&matUnits);
		TEST_CALL_REPORT( "ProMaterialPropertySet()", 
	    	"ProTestMaterialAction()",status, status != PRO_TK_NO_ERROR);
	break;
    case USER_READ:
	ProUtilMsgPrint((char*)"gen", (char*)"TEST %0s", (char*)"Enter material name:");
	status = ProMessageStringRead(PRO_NAME_SIZE, w_name);
	if (status != PRO_TK_NO_ERROR)
	    break;
	status = ProMaterialfileRead(*part, w_name);
       	TEST_CALL_REPORT("ProMaterialfileRead()", 
	   	"ProTestMaterialAction()",status,status != PRO_TK_NO_ERROR);
	break;
    case USER_WRITE:
	status = ProUtilSelectMaterial(part, &material);
	if (status != PRO_TK_NO_ERROR)
	    break;
	ProUtilMsgPrint((char*)"gen",(char*)"TEST %0s",(char*)"Enter file name to store material:");
	status = ProMessageStringRead(PRO_NAME_SIZE, w_name);
	ProWstringToString(name, w_name);
	if (strchr(name, '.') == NULL)
	    ProUtilstrcat(name, ".mat");
	ProStringToWstring(w_name, name);
	status = ProMaterialfileWrite(&material, w_name);
       	TEST_CALL_REPORT("ProMaterialfileWrite()", 
	   	"ProTestMaterialAction()",status,status != PRO_TK_NO_ERROR);
	if (status == PRO_TK_NO_ERROR)
	    ProUtilMsgPrint((char*)"gen", (char*)"TEST %0s", 
					"Material file stored successfilly");
	break;
    default:
	ProUtilMsgPrint((char*)"gen", (char*)"TEST %0s", (char*)"Error!!");
	break;
    }
    return (0);
}