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


/*----------------------------------------------------------------------------*\
Pro/TOOLKIT includes
\*----------------------------------------------------------------------------*/
#include <ProToolkit.h>
#include <ProMenu.h>
#include <ProMenuBar.h>
#include <ProMessage.h>
#include <ProUICmd.h>
#include <ProUtil.h>
#include <ProTKRunTime.h>
#include <PTApplsUnicodeUtils.h>
/*----------------------------------------------------------------------------*\
Application includes
\*----------------------------------------------------------------------------*/
#include "TestError.h"
#include "TestMenu.h"
#include "UtilMessage.h"

/*----------------------------------------------------------------------------*\
Application data types
\*----------------------------------------------------------------------------*/
typedef struct user_command
{
    char *name;
    uiCmdCmdId id;
} UserCommand;

typedef struct user_check_but
{
    uiCmdCmdId command;
    ProBoolean state;
} UserCheckBut;

typedef struct user_push_but
{
    char *action_name;
    uiCmdCmdActFn action_cb;

    char *button_name;
    char *button_label;
    char *button_help;
} UserPushButton;

/*----------------------------------------------------------------------------*\
Application global/external data
\*----------------------------------------------------------------------------*/
static wchar_t msgfil[] = 

    { 'm','e','n','u','b','a','r','_','m','s','g','.','t','x','t','\0'};

static UserCheckBut check_but[2];
static uiCmdAccessState access_state = ACCESS_AVAILABLE;
static FILE *log_file = NULL;

static UserCommand user_actions[] = {
  {(char*)"TestPushButtonAct1", (uiCmdCmdId)NULL},
	{(char*)"TestPushButtonAct2", (uiCmdCmdId)NULL},
	{(char*)"TestCheckButtonOpt1", (uiCmdCmdId)NULL},
	{(char*)"TestCheckButtonOpt2", (uiCmdCmdId)NULL},
	{(char*)"TestRadioGroupOpt",  (uiCmdCmdId)NULL}};

/*====================================================================*\
    FUNCTION :	ProUtilLogFileWrite()
    PURPOSE  :  Write message to the log file
\*====================================================================*/
static void ProUtilLogFileWrite(
    char *func_type,
    uiCmdCmdId command)
{
    int i;
    
    if (log_file == NULL)
	return;

    if (command == NULL)
    {
        ProTKFprintf(log_file, "%s function is called.\n", func_type);
	ProTKPrintf( "%s function is called.\n", func_type);
	return;
    }

    for (i=0; i<sizeof(user_actions)/sizeof(user_actions[0]); i++)
    {
	if (user_actions[i].id == command)
	{
	    ProTKFprintf(log_file, "%s function is called for action %s.\n",
		func_type, user_actions[i].name);
	    ProTKPrintf("%s function is called for action %s.\n",
		func_type, user_actions[i].name);
	    break;
	}
    }
}


/*====================================================================*\
    FUNCTION :	ProTestAccessFunction()
    PURPOSE  :   Enable access
\*====================================================================*/
static uiCmdAccessState ProTestAccessFunction(uiCmdAccessMode access_mode)
{
    TEST_CALL_REPORT("uiCmdAccessFn()", "ProTestAccessFunction()", PRO_TK_NO_ERROR, 0);
    
    ProUtilLogFileWrite( (char*)"!Access", NULL);
    return (ACCESS_AVAILABLE);
}

/*====================================================================*\
    FUNCTION :	ProTestAccessFunction()
    PURPOSE  :  Disable access
\*====================================================================*/
static uiCmdAccessState ProTestAccess(uiCmdAccessMode access_mode)
{
    TEST_CALL_REPORT("uiCmdAccessFn()", "ProTestAccessFunction()", PRO_TK_NO_ERROR, 0);
    
    ProUtilLogFileWrite( (char*)"!Access", NULL);
    return (access_state);
}


/*====================================================================*\
    FUNCTION :	ProTestRadioButtonValue()
    PURPOSE  :  Set value for radio group
\*====================================================================*/
int ProTestRadioButtonValue(
    uiCmdCmdId command,
    uiCmdValue *p_value)
{
    ProError err;
    ProMenuItemName  name;

    ProUtilLogFileWrite((char*)"Set_value callback", command);    
    TEST_CALL_REPORT("uiCmdCmdValFn()", "ProTestRadioButtonValue()", PRO_TK_NO_ERROR, 0);

#if 0
    err = ProMenubarMenuRadiogrpValueGet (p_value, name);
    TEST_CALL_REPORT("ProMenubarMenuRadiogrpValueGet()", 
		    "ProTestRadioButtonValue()", err, err != PRO_TK_NO_ERROR);

    err = ProMenubarMenuRadiogrpValueSet(p_value, name);
    TEST_CALL_REPORT("ProMenubarMenuRadiogrpValueSet()", 
		    "ProTestRadioButtonValue()", err, err != PRO_TK_NO_ERROR);
#endif 
    return (0);
}

/*====================================================================*\
    FUNCTION :	ProTestRadioButton()
    PURPOSE  :  Callback functions for radio group options
\*====================================================================*/
int ProTestRadioButton(
    uiCmdCmdId command,
    uiCmdValue *p_value)
{
    ProError err;
    ProMenuItemName  name;    

    ProUtilLogFileWrite((char*)"Callback", command);
    TEST_CALL_REPORT("uiCmdCmdActFn()", "ProTestRadioButton()", PRO_TK_NO_ERROR, 0);
    ProMessageDisplay(msgfil, (char*)"TEST Radio Group pressed.");
    
    err = ProMenubarMenuRadiogrpValueGet (p_value, name);
    TEST_CALL_REPORT("ProMenubarMenuRadiogrpValueGet()", 
		    "ProTestRadioButtonValue()", err, err != PRO_TK_NO_ERROR);  
    return(0);
}

/*====================================================================*\
    FUNCTION :	ProTestCheckButtonValue()
    PURPOSE  :  Set new value for check buttons
\*====================================================================*/
int ProTestCheckButtonValue(
    uiCmdCmdId command,
    uiCmdValue *p_value)
{
    ProError err;
    ProBoolean value;
    int i;

    TEST_CALL_REPORT("uiCmdCmdValFn()", "ProTestCheckButtonValue()", PRO_TK_NO_ERROR, 0);

    for (i=0; i<sizeof(check_but)/sizeof(check_but[0]); i++)

	if (check_but[i].command == command)
	{
    	    err = ProMenubarmenuChkbuttonValueGet (p_value, &value);
	    TEST_CALL_REPORT("ProMenubarmenuChkbuttonValueGet()", 
		"ProTestCheckButtonValue()", err, err != PRO_TK_NO_ERROR);
	
	    if (value == check_but[i].state)
		continue;
	    

	    ProUtilLogFileWrite((char*)"Set_value callback", command);    
    
	    err = ProMenubarmenuChkbuttonValueSet(p_value, check_but[i].state);
	    TEST_CALL_REPORT("ProMenubarmenuChkbuttonValueSet()", 
		"ProTestCheckButtonValue()", err, err != PRO_TK_NO_ERROR);
	    break;
	}

    return(0);
}

/*====================================================================*\
    FUNCTION :	ProTestCheckButton()
    PURPOSE  :  Callback function for check button options
\*====================================================================*/
int ProTestCheckButton(    
    uiCmdCmdId command,
    uiCmdValue *p_value,
    void *p_push_command_data)
{
    int i;

    ProUtilLogFileWrite((char*)"Callback", command);    
    TEST_CALL_REPORT("uiCmdCmdActFn()", "ProTestCheckButton()", PRO_TK_NO_ERROR, 0);
    ProMessageDisplay(msgfil, (char*)"TEST Check Button pressed.");

    for (i=0; i<sizeof(check_but)/sizeof(check_but[0]); i++)
	if (check_but[i].command == command)
	{
	  /*  Change state of pressed button */

            if (check_but[i].state == PRO_B_FALSE)
            	 check_but[i].state = PRO_B_TRUE;
            else 
             	 check_but[i].state = PRO_B_FALSE;
            
          break;
	}

    return(0);
}

/*====================================================================*\
    FUNCTION :	ProTestPushButton()
    PURPOSE  :  Callback function for push button actions
\*====================================================================*/
int ProTestPushButton(uiCmdCmdId command)
{
    ProUtilLogFileWrite((char*)"Callback", command);
    TEST_CALL_REPORT("uiCmdCmdActFn()", "ProTestPushButton()", PRO_TK_NO_ERROR, 0);
    ProMessageDisplay(msgfil, (char*)"TEST Push Button pressed.");

    return(0);
}


/*====================================================================*\
    FUNCTION :	ProTestBracketFunc()
    PURPOSE  :  Bracket function, called before and after actions
\*====================================================================*/
int ProTestBracketFunc(
    uiCmdCmdId command,
    uiCmdValue *p_new_value,
    int entering_command,
    void **data)
{
    ProUtilLogFileWrite(entering_command ? (char*)"Pre-action" : (char*)"Post-action", 
	command);    
    TEST_CALL_REPORT("uiCmdCmdBktFn()", "ProTestBracketFunc()", PRO_TK_NO_ERROR, 0);

    return (entering_command);
}


/*====================================================================*\
    FUNCTION :	ProUtilAccessSet()
    PURPOSE  :  change access to the user actions. Add/remove access function
\*====================================================================*/
ProError ProUtilAccessSet(uiCmdAccessState state)
{
    ProError	err;
    static uiCmdAccessId 
	access_id[sizeof(user_actions)/sizeof(user_actions[0])];
    int i;

    TEST_CALL_REPORT("uiCmdCmdActFn()", "ProUtilAccessSet()", PRO_TK_NO_ERROR, 0);

    for (i=0; i<sizeof(user_actions)/sizeof(user_actions[0]); i++)
    {
	if (user_actions[i].id == (uiCmdCmdId)NULL)
	    continue;

	if (access_id[i] != (uiCmdAccessId)NULL)
	{
	    err = ProCmdAccessFuncRemove(user_actions[i].id, access_id[i]);
	    TEST_CALL_REPORT("ProCmdAccessFuncRemove()", 
			    "ProUtilAccessSet()", err, err != PRO_TK_NO_ERROR);

	    access_id[i] = (uiCmdAccessId)NULL;
	}

	access_state = state;
	if (state != ACCESS_AVAILABLE)
	{
	    err = ProCmdAccessFuncAdd(user_actions[i].id, 
		(uiCmdAccessFn)ProTestAccess, &access_id[i]);
	    TEST_CALL_REPORT("ProCmdAccessFuncAdd()", 
			    "ProUtilAccessSet()", err, err != PRO_TK_NO_ERROR);
	}
    }
    return (err);
}

/*====================================================================*\
    FUNCTION :	ProTestPushButtonAccessAvailable()
    PURPOSE  :  Callback function. Set access to user actions available
\*====================================================================*/
int ProTestPushButtonAccessAvailable()
{
    ProUtilAccessSet(ACCESS_AVAILABLE);
    return(0);
}

/*====================================================================*\
    FUNCTION :	ProTestPushButtonAccessDisallow()
    PURPOSE  :  Callback function. Set access to user actions disallow
\*====================================================================*/
int ProTestPushButtonAccessDisallow()
{
    ProUtilAccessSet(ACCESS_DISALLOW);
    return(0);
}

/*====================================================================*\
    FUNCTION :	ProTestPushButtonAccessInvisible()
    PURPOSE  :  Callback function. Set access to user actions invisible
\*====================================================================*/
int ProTestPushButtonAccessInvisible()
{
    ProUtilAccessSet(ACCESS_INVISIBLE);
    return(0);
}

/*====================================================================*\
    FUNCTION :	ProTestPushButtonAccessUnavailable()
    PURPOSE  :  Callback function. Set access to user actions unavailable
\*====================================================================*/
int ProTestPushButtonAccessUnavailable()
{
    ProUtilAccessSet(ACCESS_UNAVAILABLE);
    return(0);
}

/*====================================================================*\
    FUNCTION :	ProTestPushButtonLogStart()
    PURPOSE  :  Callback function. Open log file for output
\*====================================================================*/
int ProTestPushButtonLogStart()
{
    if (log_file == NULL)
    {
	log_file = (FILE *)PTApplsUnicodeFopen("menubar.log", "w");
    }
    return (0);
}

/*====================================================================*\
    FUNCTION :	ProTestPushButtonLogStop()
    PURPOSE  :  Callback function. Close log file
\*====================================================================*/
int ProTestPushButtonLogStop()
{
    if (log_file != NULL)
    {
	fclose(log_file);
	log_file = NULL;
    }
    return (0);
}

/*====================================================================*\
    FUNCTION :	ProUtilActionsIdsGet()
    PURPOSE  :  Get Ids for user actions added to menu bar
\*====================================================================*/
ProError ProUtilActionsIdsGet()
{
    ProError err;
    int i;

    for (i=0; i<sizeof(user_actions)/sizeof(user_actions[0]); i++)
    {
	err = ProCmdCmdIdFind(user_actions[i].name, &user_actions[i].id);
	if (err != PRO_TK_NO_ERROR)
	    user_actions[i].id = (uiCmdCmdId)NULL;
	TEST_CALL_REPORT("ProCmdCmdIdFind()", 
			"ProUtilActionsIdsGet()", err, err != PRO_TK_NO_ERROR);
    }
    return (err);
}

/*====================================================================*\
    FUNCTION :	ProTestAddBrackets()
    PURPOSE  :  Add ids for user actions added to menu bar
\*====================================================================*/
ProError ProTestAddBrackets()
{
    ProError err;
    int i;

    for (i=0; i<sizeof(user_actions)/sizeof(user_actions[0]); i++)
    {
	if (user_actions[i].id == NULL)
	    continue;

	err = ProCmdBracketFuncAdd(user_actions[i].id, 
	     (uiCmdCmdBktFn)ProTestBracketFunc,
	     (char*)"ProTestBracketFunc", (void**)NULL);
	TEST_CALL_REPORT("ProCmdBracketFuncAdd()", 
			"ProUtilActionsIdsGet()", err, err != PRO_TK_NO_ERROR);


    }
    return (err);
}

/*============================================================================*\
  Function : ProTestMenuBar
  Purpose  : Create a menu to test Menu Bar functions
\*============================================================================*/
int ProTestMenuBar()
{
    static UserPushButton push_buts[] =
    {
	{(char*)"TestAccessInvisible", 
	 (uiCmdCmdActFn)ProTestPushButtonAccessInvisible,
	 (char*)"TestInvisible",(char*) "Invisible", (char*)"Test change access"},
	{(char*)"TestAccessUnavailable", 
	 (uiCmdCmdActFn)ProTestPushButtonAccessUnavailable,
	 (char*)"TestUnavailable", (char*)"Unavailable", (char*)"Test change access"},
	{(char*)"TestAccessDisallow", 
	 (uiCmdCmdActFn)ProTestPushButtonAccessDisallow,
	 (char*)"TestDisallow", (char*)"Disallow", (char*)"Test change access"},
	{(char*)"TestAccessAvailable", 
	 (uiCmdCmdActFn)ProTestPushButtonAccessAvailable,
	 (char*)"TestAvailable", (char*)"Available", (char*)"Test change access"},
	{(char*)"TestLogStart", 
	 (uiCmdCmdActFn)ProTestPushButtonLogStart,
	 (char*)"TestStart", (char*)"Log start", (char*)"Start log"},
	{(char*)"TestLogStop", 
	 (uiCmdCmdActFn)ProTestPushButtonLogStop,
	 (char*)"TestStop", (char*)"Log stop", (char*)"Stop log"}
    };

    ProError err;
    uiCmdCmdId   push_act, push_act2, action; 
    uiCmdCmdId   radio_act;
    int i;

    static ProMenuItemName radio_group_items[]=
	{"TestRadio1", "TestRadio2", "TestRadio3", ""};
    static ProMenuItemLabel radio_group_labels[]=
	{"Radio button 1", "Radio button 2", "Radio button 3", ""};
    static ProMenuLineHelp radio_group_help[]=
	{"Test radio button", "Test radio button", "Test radio button", ""};
/*---------------------------------------------------------------------*\
    Add new button to the menu bar
\*---------------------------------------------------------------------*/
    err = ProMenubarMenuAdd((char*)"TestMenuBar", (char*)"-MenuBar", (char*)"Help", PRO_B_FALSE,
	msgfil);
    TEST_CALL_REPORT("ProMenubarMenuAdd()", 
			    "ProTestMenuBar()", err, err != PRO_TK_NO_ERROR);

    err = ProCmdActionAdd((char*)"TestPushButtonAct1", 
	(uiCmdCmdActFn)ProTestPushButton, uiCmdPrioDefault, 
	ProTestAccessFunction, PRO_B_TRUE, PRO_B_TRUE, &push_act);
    TEST_CALL_REPORT("ProCmdActionAdd()", 
			"ProTestMenuBar()", err, err != PRO_TK_NO_ERROR);

    err = ProCmdActionAdd((char*)"TestPushButtonAct2", 
	(uiCmdCmdActFn)ProTestPushButton, uiCmdPrioDefault, 
	ProTestAccessFunction, PRO_B_TRUE, PRO_B_TRUE, &push_act2);
    TEST_CALL_REPORT("ProCmdActionAdd()", 
			"ProTestMenuBar()", err, err != PRO_TK_NO_ERROR);

    err = ProCmdOptionAdd((char*)"TestCheckButtonOpt1", 
	(uiCmdCmdActFn)ProTestCheckButton, PRO_B_TRUE, 
	(uiCmdCmdValFn)ProTestCheckButtonValue, 
	ProTestAccessFunction, PRO_B_TRUE, PRO_B_TRUE, &check_but[0].command);
    TEST_CALL_REPORT("ProCmdOptionAdd()", 
			"ProTestMenuBar()", err, err != PRO_TK_NO_ERROR);

    err = ProCmdOptionAdd((char*)"TestCheckButtonOpt2", 
	(uiCmdCmdActFn)ProTestCheckButton, PRO_B_TRUE, 
	(uiCmdCmdValFn)ProTestCheckButtonValue, 
	ProTestAccessFunction, PRO_B_TRUE, PRO_B_TRUE, &check_but[1].command);
    TEST_CALL_REPORT("ProCmdOptionAdd()", 
			"ProTestMenuBar()", err, err != PRO_TK_NO_ERROR);

    err = ProCmdOptionAdd((char*)"TestRadioGroupOpt", 
	(uiCmdCmdActFn)ProTestRadioButton, PRO_B_FALSE, 
	(uiCmdCmdValFn)ProTestRadioButtonValue, 
	ProTestAccessFunction, PRO_B_TRUE, PRO_B_TRUE, &radio_act);
    TEST_CALL_REPORT("ProCmdActionAdd()", 
			"ProTestMenuBar()", err, err != PRO_TK_NO_ERROR);

    err = ProMenubarmenuPushbuttonAdd((char*)"TestMenuBar", (char*)"TestPushBut1", (char*)"Push button 1", 
	(char*)"Test push button", (char*)"", PRO_B_FALSE, push_act, msgfil);
    TEST_CALL_REPORT("ProMenubarmenuPushbuttonAdd()", 
			"ProTestMenuBar()", err, err != PRO_TK_NO_ERROR);

    err = ProMenubarmenuMenuAdd((char*)"TestMenuBar", (char*)"TestMenuBarMenu", (char*)"Submenu", 
	(char*)"TestPushBut1", PRO_B_FALSE, msgfil);
    TEST_CALL_REPORT("ProMenubarmenuMenuAdd()", 
			"ProTestMenuBar()", err, err != PRO_TK_NO_ERROR);

    err = ProMenubarmenuPushbuttonAdd((char*)"TestMenuBarMenu", (char*)"TestPushBut2", 
	(char*)"Push button 2",
				      (char*)"Test push button", (char*)"", PRO_B_FALSE, push_act2, msgfil);
    TEST_CALL_REPORT("ProMenubarmenuPushbuttonAdd()", 
			"ProTestMenuBar()", err, err != PRO_TK_NO_ERROR);

    err = ProMenubarmenuChkbuttonAdd((char*)"TestMenuBarMenu", (char*)"TestChkBut2", 
	(char*)"Check button 2", 
	(char*)"Test check button", (char*)"TestPushBut2", PRO_B_TRUE, check_but[1].command, 
	msgfil);
    TEST_CALL_REPORT("ProMenubarmenuChkbuttonAdd()", 
			"ProTestMenuBar()", err, err != PRO_TK_NO_ERROR);

    err = ProMenubarmenuChkbuttonAdd((char*)"TestMenuBar", (char*)"TestChkBut1", (char*)"Check button 1", 
	(char*)"Test check button", (char*)"TestPushBut1", PRO_B_TRUE, check_but[0].command, 
	msgfil);
    TEST_CALL_REPORT("ProMenubarmenuChkbuttonAdd()", 
			"ProTestMenuBar()", err, err != PRO_TK_NO_ERROR);

    for (i=0; i<sizeof(push_buts)/sizeof(push_buts[0]); i++)
    {
	err = ProCmdActionAdd(push_buts[i].action_name, 
	    push_buts[i].action_cb, uiCmdPrioDefault, 
	    ProTestAccessFunction, PRO_B_TRUE, PRO_B_TRUE, &action);
	TEST_CALL_REPORT("ProCmdActionAdd()", 
		    "ProTestMenuBar()", err, err != PRO_TK_NO_ERROR);

	err = ProMenubarmenuPushbuttonAdd((char*)"TestMenuBar", push_buts[i].button_name,
	    push_buts[i].button_label, push_buts[i].button_help, 
					  i == 0 ? (char*)"TestChkBut1" : push_buts[i-1].button_name, PRO_B_TRUE,
	    action, msgfil);
	TEST_CALL_REPORT("ProMenubarmenuPushbuttonAdd()", 
		    "ProTestMenuBar()", err, err != PRO_TK_NO_ERROR);
    }


    err = ProMenubarmenuRadiogrpAdd((char*)"TestMenuBarMenu", (char*)"TestRadioGrp1",
	3, radio_group_items, radio_group_labels, radio_group_help, 
	(char*)"TestChkBut2", PRO_B_TRUE, radio_act, msgfil);
    TEST_CALL_REPORT("ProMenubarmenuRadiogrpAdd()", 
			"ProTestMenuBar()", err, err != PRO_TK_NO_ERROR);

    err = ProUtilActionsIdsGet();
    err = ProTestAddBrackets();

    return(0);
}