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

/*--------------------------------------------------------------------*\
Pro/TOOLKIT includes
\*--------------------------------------------------------------------*/
#include <ProDrawing.h>
#include <ProSelection.h>
#include <ProMessage.h>
#include <ProMenu.h>
#include <ProMdl.h>
#include <ProModelitem.h>
#include <ProWindows.h>
#include <ProDwgtable.h>

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

/*--------------------------------------------------------------------*\
C System includes
\*--------------------------------------------------------------------*/

/*--------------------------------------------------------------------*\
Application includes
\*--------------------------------------------------------------------*/
#include "TestError.h"
#include "UtilString.h"
#include "UtilFiles.h"
#include "UtilMessage.h"
#include <ProTKRunTime.h>

/*--------------------------------------------------------------------*\
Application macros
\*--------------------------------------------------------------------*/
#define NEXT_SHEET 0
#define PREV_SHEET 1
#define SET_SHEET  2

/*--------------------------------------------------------------------*\
Application data types
\*--------------------------------------------------------------------*/

/*--------------------------------------------------------------------*\
Application global/external data
\*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*\
Functions prototype
\*--------------------------------------------------------------------*/
int ProTestDrwSheetAdd      (ProDrawing* drawing);
int ProTestDrwSheetDel      (ProDrawing* drawing);
int ProTestDrwSheetReorder  (ProDrawing* drawing);
int ProTestDrwSheetSet      (ProDrawing* drawing, int val);
int ProTestDrwSheetFormat   (ProDrawing* drawing);
int ProTestDrwSheetScale    (ProDrawing* drawing);

/*====================================================================*\
Function:  ProTestDrwSheets                               
Purpose:   Make user menu
\*====================================================================*/
int ProTestDrwSheets  (ProDrawing* drawing)
{
    int             menu_id;
    ProError        status;

    /* Setup the menus for test */
    status = ProMenuFileRegister((char*)"-Sheets",(char*)"tksheet.mnu", &menu_id);
    TEST_CALL_REPORT ("ProMenuFileRegister()", "ProTestDrwSheets()",
        status, status != PRO_TK_NO_ERROR);
    status = ProMenubuttonActionSet ((char*)"-Sheets", (char*)"-Previous",
                (ProMenubuttonAction)ProTestDrwSheetSet, drawing, PREV_SHEET);
    TEST_CALL_REPORT ("ProMenubuttonActionSet()", "ProTestDrwSheets()",
        status, status != PRO_TK_NO_ERROR);
    status = ProMenubuttonActionSet ((char*)"-Sheets", (char*)"-Next",
                (ProMenubuttonAction)ProTestDrwSheetSet, drawing, NEXT_SHEET);
    TEST_CALL_REPORT ("ProMenubuttonActionSet()", "ProTestDrwSheets()",
        status, status != PRO_TK_NO_ERROR);
    status = ProMenubuttonActionSet ((char*)"-Sheets", (char*)"-Set Current",
                (ProMenubuttonAction)ProTestDrwSheetSet, drawing, SET_SHEET);
    TEST_CALL_REPORT ("ProMenubuttonActionSet()", "ProTestDrwSheets()",
        status, status != PRO_TK_NO_ERROR);
    status = ProMenubuttonActionSet ((char*)"-Sheets", (char*)"-Add",
                (ProMenubuttonAction)ProTestDrwSheetAdd, drawing, 0);
    TEST_CALL_REPORT ("ProMenubuttonActionSet()", "ProTestDrwSheets()",
        status, status != PRO_TK_NO_ERROR);
    status = ProMenubuttonActionSet ((char*)"-Sheets", (char*)"-Remove",
                (ProMenubuttonAction)ProTestDrwSheetDel, drawing, 0);
    TEST_CALL_REPORT ("ProMenubuttonActionSet()", "ProTestDrwSheets()",
        status, status != PRO_TK_NO_ERROR);
    status = ProMenubuttonActionSet ((char*)"-Sheets", (char*)"-Reorder",
                (ProMenubuttonAction)ProTestDrwSheetReorder, drawing, 0);
    TEST_CALL_REPORT ("ProMenubuttonActionSet()", "ProTestDrwSheets()",
        status, status != PRO_TK_NO_ERROR);
    status = ProMenubuttonActionSet ((char*)"-Sheets", (char*)"-Add Format",
                (ProMenubuttonAction)ProTestDrwSheetFormat, drawing, 0);
    TEST_CALL_REPORT ("ProMenubuttonActionSet()", "ProTestDrwSheets()",
        status, status != PRO_TK_NO_ERROR);
    status = ProMenubuttonActionSet ((char*)"-Sheets", (char*)"-Scale",
                (ProMenubuttonAction)ProTestDrwSheetScale, drawing, 0);
    TEST_CALL_REPORT ("ProMenubuttonActionSet()", "ProTestDrwSheets()",
        status, status != PRO_TK_NO_ERROR);

    status = ProMenubuttonActionSet ((char*)"-Sheets", (char*)"-Sheets",
                (ProMenubuttonAction)ProMenuDelete, NULL, 0);
    TEST_CALL_REPORT ("ProMenubuttonActionSet()", "ProTestDrwSheets()",
        status, status != PRO_TK_NO_ERROR);

    status = ProMenuCreate(PROMENUTYPE_MAIN,(char*)"-Sheets", &menu_id);
    TEST_CALL_REPORT ("ProMenuCreate()", "ProTestDrwSheets()",
        status, status != PRO_TK_NO_ERROR);

    status = ProMenuProcess((char*)"", &menu_id);
    TEST_CALL_REPORT ("ProMenuProcess()", "ProTestDrwSheets()",
        status, status != PRO_TK_NO_ERROR);

    return(0);
}

/*====================================================================*\
Function:  ProTestDrwSheetAdd                                    
Purpose:   Add sheet to the drawing 
\*====================================================================*/
int ProTestDrwSheetAdd  (ProDrawing* drawing)
{
    int             sheet_num;
    ProError        status;
    ProCharLine     c_name;

    status = ProDrawingSheetCreate (*drawing, &sheet_num);
    TEST_CALL_REPORT ("ProDrawingSheetCreate()", "ProTestDrwSheetAdd()",
        status, status != PRO_TK_NO_ERROR);

    if (status == PRO_TK_NO_ERROR)
    {
        ProTKSprintf (c_name, "Sheet %0d added to drawing.", sheet_num);
    }
    else
    {
        ProTKSprintf (c_name, "Cant add sheet to drawing.");
    }
    ProUtilMsgPrint("gen", "TEST %0s", c_name);

    /* repaint the current window */
    status = ProWindowRepaint (PRO_VALUE_UNUSED);
    TEST_CALL_REPORT ("ProWindowRepaint()", "ProTestDrwSheetAdd()",
        status, status != PRO_TK_NO_ERROR);

    return (sheet_num);
}

/*====================================================================*\
Function:  ProTestDrwSheetPrompt                                    
Purpose:   Read sheet number 
\*====================================================================*/
int ProTestDrwSheetPrompt (ProDrawing drawing, char *prompt)
{
    int             sheet_num, num_sheets;
    int             i_range[2] = {1, 1};
    ProError        status;
    ProCharLine     c_line;

    status = ProDrawingSheetsCount (drawing, &num_sheets);
    TEST_CALL_REPORT ("ProDrawingSheetsCount()", "ProTestDrwSheetPrompt()",
        status, status != PRO_TK_NO_ERROR);
    
    if(status == PRO_TK_NO_ERROR)
    {
        i_range[1] = num_sheets;

        ProTKSprintf (c_line, "%s [1-%0d]:", prompt, i_range[1]);
        ProUtilMsgPrint ("gen", "TEST %0s", c_line);

        status = ProMessageIntegerRead (i_range, &sheet_num);

        if (status == PRO_TK_NO_ERROR)
            return sheet_num;

#if 0
        if (status == PRO_TK_MSG_USER_QUIT)
        {
            status = ProDrawingCurrentSheetGet(drawing, &sheet_num);
            TEST_CALL_REPORT ("ProDrawingCurrentSheetGet()",
                "ProTestDrwSheetPrompt()", status, status != PRO_TK_NO_ERROR);

            if (status == PRO_TK_NO_ERROR)
                return sheet_num;
        }
#endif
    }

    return -1;
}

/*====================================================================*\
Function:  ProTestDrwSheetDel                                    
Purpose:   Delete sheet from the drawing 
\*====================================================================*/
int ProTestDrwSheetDel (ProDrawing* drawing)
{
    int             sheet_num;
    ProError        status;
    ProCharLine     c_line;

    /* get sheet number on which to create view */
    sheet_num = ProTestDrwSheetPrompt (*drawing,
                    (char*)"Enter sheet number for delete");
    if (sheet_num == -1)
        return(-1);

    status = ProDrawingSheetDelete (*drawing, sheet_num);
    TEST_CALL_REPORT ("ProDrawingSheetDelete()", "ProTestDrwSheetDel()",
        status, status != PRO_TK_NO_ERROR);

    if (status == PRO_TK_NO_ERROR)
    {
        ProTKSprintf(c_line, " Sheet No. %0d deleted from drawing.", sheet_num);
    } 
    else
    {
        ProTKSprintf (c_line, "Cant delete sheet %0d from drawing.", sheet_num);
    }

    ProUtilMsgPrint("gen", "TEST %0s", c_line);

    /* repaint the currentwindow */
    status = ProWindowRepaint(PRO_VALUE_UNUSED);
    TEST_CALL_REPORT ("ProWindowRepaint()", "ProTestDrwSheetDel()",
        status, status != PRO_TK_NO_ERROR);

    return (sheet_num);
}

/*====================================================================*\
Function:  ProTestDrwSheetReorder                                    
Purpose:   Reorder sheet in the drawing 
\*====================================================================*/
int ProTestDrwSheetReorder (ProDrawing* drawing)
{
    int         from_sheet, to_sheet;
    ProError    status;

    from_sheet = ProTestDrwSheetPrompt (*drawing, (char*)"Enter sheet number to reorder");
    if (from_sheet == -1)
        return (-1);

    to_sheet = ProTestDrwSheetPrompt (*drawing, (char*)"Enter new number");
    if (to_sheet == -1)
        return (-1);

    status = ProDrawingSheetsReorder (*drawing, from_sheet, to_sheet);
    TEST_CALL_REPORT ("ProDrawingSheetCreate()", "ProTestDrwSheetReorder()",
        status, status != PRO_TK_NO_ERROR);

    /* repaint the current window */
    status = ProWindowRepaint(PRO_VALUE_UNUSED);
    TEST_CALL_REPORT ("ProWindowRepaint()", "ProTestDrwSheetReorder()",
        status, status != PRO_TK_NO_ERROR);

    return (0);
}

/*====================================================================*\
Function:  ProTestDrwSheetSet                                    
Purpose:   Setup current sheet in the drawing 
\*====================================================================*/
int ProTestDrwSheetSet (ProDrawing* drawing, int val)
{
    int         num_sheets, cur_sheet;
    ProError    status;

    status = ProDrawingSheetsCount (*drawing, &num_sheets);
    TEST_CALL_REPORT ("ProDrawingSheetsCount()", "ProTestDrwSheetSet()",
        status, status != PRO_TK_NO_ERROR);

    if(val == SET_SHEET)
    {
        cur_sheet = ProTestDrwSheetPrompt(*drawing,
                        (char*)"Enter new number of sheet");
        
        if (cur_sheet == -1)
            return(-1);
    }
    else
    {
        status = ProDrawingCurrentSheetGet(*drawing, &cur_sheet);
        TEST_CALL_REPORT ("ProDrawingCurrentSheetGet()", "ProTestDrwSheetSet()",
            status, status != PRO_TK_NO_ERROR);

        cur_sheet+=(val==NEXT_SHEET)?(+1):(-1);
        cur_sheet =(cur_sheet>num_sheets)?(1):
                        ((cur_sheet<1)?(num_sheets):cur_sheet);
    }

    status = ProDrawingCurrentSheetSet (*drawing, cur_sheet);
    TEST_CALL_REPORT ("ProDrawingCurrentSheetGet()", "ProTestDrwSheetSet()",
        status, status != PRO_TK_NO_ERROR);

    status = ProWindowRepaint(PRO_VALUE_UNUSED);
    TEST_CALL_REPORT ("ProWindowRepaint()", "ProTestDrwSheetSet()",
        status, status != PRO_TK_NO_ERROR);
    return (0);
}

/*====================================================================*\
Function:  ProTestDrwSheetReorder                                    
Purpose:   Add/Replace drawing format in the current sheet
\*====================================================================*/
int ProTestDrwSheetFormat (ProDrawing* drawing)
{
    int             version;
    ProError        status;
    ProMdl          format;
    ProLine         filter = {'*','.','f','r','m','\0'};
    ProPath         *path_arr, sel_path, path;
    ProName         *name_arr;
	ProMdlName      w_name;
	ProMdlExtension w_type;
    ProType         type = (ProType)PRO_MDL_DWGFORM;

    /* No default dirs */
    status = ProArrayAlloc (0, sizeof(ProPath), 1, (ProArray*)&path_arr);
    TEST_CALL_REPORT ("ProArrayAlloc()", "ProTestDrwSheetFormat()",
        status, status != PRO_TK_NO_ERROR);

    status = ProArrayAlloc (0, sizeof(ProName), 1, (ProArray*)&name_arr);
    TEST_CALL_REPORT ("ProArrayAlloc()", "ProTestDrwSheetFormat()",
        status, status != PRO_TK_NO_ERROR);

    /* Open file */
    status = ProFileMdlnameOpen (NULL, filter, path_arr, name_arr,
                         NULL, NULL, sel_path);
    TEST_CALL_REPORT ("ProFileMdlnameOpen()", "ProTestDrwSheetFormat()",
        status, status != PRO_TK_NO_ERROR);

    if (status == PRO_TK_NO_ERROR)
    {        
        status = ProFileMdlnameParse (sel_path, path, w_name, w_type, &version);
        TEST_CALL_REPORT ("ProFileMdlnameParse()", "ProTestDrwSheetFormat()",
            status, status != PRO_TK_NO_ERROR);

        status = ProPathMdlnameCreate (NULL, w_name, w_type, PRO_VALUE_UNUSED, path);
        TEST_CALL_REPORT ("ProPathMdlnameCreate()", "ProTestDrwSheetFormat()",
            status, status != PRO_TK_NO_ERROR);
        
        status = ProMdlnameRetrieve (w_name, (ProMdlfileType)type, &format);
        TEST_CALL_REPORT ("ProMdlnameRetrieve()", "ProTestDrwSheetFormat()",
            status, status != PRO_TK_NO_ERROR);

        status = ProDrawingFormatAdd (*drawing, 0, NULL, format, 0);
        TEST_CALL_REPORT ("ProDrawingFormatAdd()", "ProTestDrwSheetFormat()",
            status, status != PRO_TK_NO_ERROR);
    }

    status = ProArrayFree((ProArray*)&path_arr);
    TEST_CALL_REPORT ("ProArrayFree()", "ProTestDrwSheetFormat()",
        status, status != PRO_TK_NO_ERROR);

    status = ProArrayFree((ProArray*)&name_arr);
    TEST_CALL_REPORT ("ProArrayFree()", "ProTestDrwSheetFormat()",
        status, status != PRO_TK_NO_ERROR);

    status = ProWindowRepaint (PRO_VALUE_UNUSED);
    TEST_CALL_REPORT ("ProWindowRepaint()", "ProTestDrwSheetFormat()",
        status, status != PRO_TK_NO_ERROR);
        
    return (0);
}

/*====================================================================*\
Function:  ProTestDrwSheetScale                                    
Purpose:   Set scale for the current sheet
\*====================================================================*/
int ProTestDrwSheetScale (ProDrawing* drawing)
{
    int             sheet;
    double          scale;
    double          range[2] = {1e-3, 1e3};
    ProCharLine     line;
    ProError        status;

    status = ProDrawingCurrentSheetGet (*drawing, &sheet);
    TEST_CALL_REPORT ("ProDrawingCurrentSheetGet()", "ProTestDrwSheetScale()",
        status, status != PRO_TK_NO_ERROR);

    status = ProDrawingScaleGet (*drawing, NULL, sheet, &scale);
    TEST_CALL_REPORT ("ProDrawingScaleGet()", "ProTestDrwSheetScale()",
        status, status != PRO_TK_NO_ERROR);

    ProTKSprintf(line, " Input scale(%2.2f) for sheet[%d] (%2.2f...%2.2f): ",
            scale, sheet, range[0], range[1]);
    ProUtilMsgPrint("gen", "TEST %0s", line);

    if (ProMessageDoubleRead (range, &scale) != PRO_TK_NO_ERROR)
        return (0);

    status = ProDrawingScaleSet (*drawing, NULL, sheet, scale);
    TEST_CALL_REPORT ("ProDrawingScaleSet()", "ProTestDrwSheetScale()",
        status, status != PRO_TK_NO_ERROR);

    status = ProDwgDraftRegenerate (*drawing);
    TEST_CALL_REPORT ("ProDwgDraftRegenerate()", "ProTestDrwSheetScale()",
        status, status != PRO_TK_NO_ERROR);

    status = ProWindowRepaint(PRO_VALUE_UNUSED);
    TEST_CALL_REPORT ("ProWindowRepaint()", "ProTestDrwSheetScale()",
        status, status != PRO_TK_NO_ERROR);

    return(0);
}