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

#include <ProDrawing.h>
#include <ProMessage.h>
#include <ProMdl.h>
#include <ProModelitem.h>
#include <ProWindows.h>
#include <ProDwgtable.h>

#include "UtilString.h"
#include "UtilFiles.h"
#include <ProTKRunTime.h>
#include <UtilMessage.h>
#include <PTApplsUnicodeUtils.h>

/*--------------------------------------------------------------------*\
  Function prototypes
\*--------------------------------------------------------------------*/
typedef struct tag_TestViewVisitData
{
    FILE        *fp;
    ProDrawing  drawing;
    int         count;
}ProTestViewVisitData;

/*===========================================================================*\
  FUNCTION: ProTestViewFilterAction
  PURPOSE:  
\*===========================================================================*/
ProError ProTestViewFilterAction (
    ProDrawing  drawing,
    ProView     view,
    ProAppData  data)
{
    TEST_CALL_REPORT ("ProViewFilterAction()", "ProTestViewFilterAction()",
        PRO_TK_NO_ERROR, 0);
    return (PRO_TK_NO_ERROR);
}

/*===========================================================================*\
  FUNCTION: ProTestSolidFilterAction
  PURPOSE:  
\*===========================================================================*/
ProError ProTestSolidFilterAction (
    ProSolid    solid,
    ProAppData  data)
{
    TEST_CALL_REPORT ("ProSolidFilterAction()", "ProTestSolidFilterAction()",
        PRO_TK_NO_ERROR, 0);
    return(PRO_TK_NO_ERROR);
}

/*===========================================================================*\
  FUNCTION: ProTestDwgtableFilterAction
  PURPOSE:  
\*===========================================================================*/
ProError ProTestDwgtableFilterAction (
    ProDwgtable *table,
    ProAppData  data)
{
    TEST_CALL_REPORT ("ProDwgtableFilterAction()",
        "ProTestDwgtableFilterAction()", PRO_TK_NO_ERROR, 0);
    return(PRO_TK_NO_ERROR);
}

/*===========================================================================*\
  FUNCTION: ProTestViewVisitAction
  PURPOSE:  
\*===========================================================================*/
ProError ProTestViewVisitAction (
    ProDrawing  drawing,
    ProView     view, 
    ProError    filter_status, 
    ProAppData  data)
{
    int                     id;
    char                    c_name[PRO_MDLNAME_SIZE];
    double                  scale;
    ProError                status;
    ProMdldata              mdldata;
    ProSolid                solid;
	ProMdlName              modelName;
	ProMdlExtension         modelExtension;
    ProTestViewVisitData   *data_ptr = (ProTestViewVisitData*)data;

    data_ptr->count++;

    status = ProDrawingViewScaleGet (drawing, view, &scale);
    TEST_CALL_REPORT ("ProDrawingViewScaleGet()",
        "ProTestViewVisitAction()", status, status!=PRO_TK_NO_ERROR);

    status = ProDrawingViewSolidGet (drawing, view, &solid);
    TEST_CALL_REPORT ("ProDrawingViewSolidGet()",
        "ProTestViewVisitAction()", status, status!=PRO_TK_NO_ERROR);

    status = ProMdlMdlnameGet (solid, modelName);
    TEST_CALL_REPORT ("ProMdlMdlnameGet()",
        "ProTestViewVisitAction()", status, status!=PRO_TK_NO_ERROR);

    status = ProMdlExtensionGet (solid, modelExtension);
    TEST_CALL_REPORT ("ProMdlExtensionGet()",
        "ProTestViewVisitAction()", status, status!=PRO_TK_NO_ERROR);

    status = ProMdlIdGet (solid, &id);
    TEST_CALL_REPORT ("ProMdlIdGet()",
        "ProTestViewVisitAction()", status, status!=PRO_TK_NO_ERROR);

    if (solid != NULL)
    {
        ProTKFprintf (data_ptr->fp,
            "[%d] Solid name: %s; solid type: %s;\n"
            "     solid id: %d; view scale: %3.3f;\n",
            data_ptr->count,
            ProWstringToString (c_name, modelName),
            ProWstringToString (c_name, modelExtension),
            id,
            scale);
    }
    else
    {
        ProTKFprintf(data_ptr->fp,
            "[%d] view scale: %3.3f;\n", data_ptr->count, scale);
    }
    return(PRO_TK_NO_ERROR);
}

/*===========================================================================*\
  FUNCTION: ProTestSolidVisitAction
  PURPOSE:  
\*===========================================================================*/
ProError ProTestSolidVisitAction (
    ProSolid   solid,
    ProError   filter_status,  
    ProAppData data)
{
    int                     i, num, id;
    char                    c_name[PRO_MDLNAME_SIZE];
    ProError                status;
    ProMdldata              mdl_data;
	ProMdlName              modelName;
	ProMdlExtension         modelExtension;
    ProTestViewVisitData   *data_ptr       = (ProTestViewVisitData*)data;
    ProSimprep             *simpreps       = NULL;
    
    data_ptr->count++;
        
    status = ProMdlMdlnameGet (solid, modelName);
    TEST_CALL_REPORT ("ProMdlMdlnameGet()", "ProTestSolidVisitAction()",
        status, status!=PRO_TK_NO_ERROR);

	status = ProMdlExtensionGet (solid, modelExtension);
    TEST_CALL_REPORT ("ProMdlExtensionGet()", "ProTestSolidVisitAction()",
        status, status!=PRO_TK_NO_ERROR);

    if (status != PRO_TK_NO_ERROR)
        return(PRO_TK_NO_ERROR);

    status = ProMdlIdGet(solid, &id);
    TEST_CALL_REPORT ("ProMdlIdGet()", "ProTestSolidVisitAction()",
        status, status!=PRO_TK_NO_ERROR);

    ProTKFprintf (data_ptr->fp,
        "[%d] Name: %s; type: %s; id: %d;\n",
        data_ptr->count,
        ProWstringToString (c_name, modelName),
        ProWstringToString (c_name, modelExtension),
        id);

/*--------------------------------------------------------------------*\
        Simp reps
\*--------------------------------------------------------------------*/
    status = ProDrawingSimprepsCollect (data_ptr->drawing,
        solid, &simpreps);
    TEST_CALL_REPORT ("ProDrawingSimprepsCollect()",
        "ProTestSolidVisitAction()", status, status!=PRO_TK_NO_ERROR);

    if (status == PRO_TK_NO_ERROR)
    {
        ProTKFprintf (data_ptr->fp, "\tSimpreps:\n");
        status = ProArraySizeGet ((ProArray)simpreps, &num);
        TEST_CALL_REPORT ("ProArraySizeGet()", "ProTestSolidVisitAction()",
            status, status!=PRO_TK_NO_ERROR);

        for (i=0; i<num; i++)
        {                    
            ProTKFprintf (data_ptr->fp, "\t[%d] Id: %d.\n",
                i+1, simpreps[i].id);
        }

        status = ProArrayFree ((ProArray*)&simpreps);
        TEST_CALL_REPORT ("ProArrayFree()", "ProTestSolidVisitAction()",
            status, status!=PRO_TK_NO_ERROR);
    }
    return(PRO_TK_NO_ERROR);
}

/*===========================================================================*\
  FUNCTION: ProTestDwgtableVisitAction
  PURPOSE:  
\*===========================================================================*/
ProError ProTestDwgtableVisitAction (
    ProDwgtable *table,
    ProError    filter_status,
    ProAppData  data)
{
    int                     n_col, n_row;
    ProError                status;
    ProBoolean              from_frm;
    ProTestViewVisitData   *data_ptr = (ProTestViewVisitData*)data;

    data_ptr->count++;
        
    status = ProDwgtableColumnsCount(table, &n_col);
    TEST_CALL_REPORT ("ProDwgtableColumnsCount()",
        "ProTestDwgtableVisitAction()", status, status!=PRO_TK_NO_ERROR);

    status = ProDwgtableRowsCount(table, &n_row);
    TEST_CALL_REPORT ("ProDwgtableRowsCount()",
        "ProTestDwgtableVisitAction()", status, status!=PRO_TK_NO_ERROR);

    status = ProDwgtableIsFromFormat(table, &from_frm);
    TEST_CALL_REPORT ("ProDwgtableIsFromFormat()",
        "ProTestDwgtableVisitAction()", status, status!=PRO_TK_NO_ERROR);

    ProTKFprintf (data_ptr->fp,
        "[%d] columns: %d; rows: %d;%s associated with the format.\n",
        data_ptr->count,
        n_col,
        n_row,
        (from_frm)?(""):("Not "));

    return(PRO_TK_NO_ERROR);
}

/*===========================================================================*\
  Function : ProTestDrwGetPlotSize
  Purpose  : To get size of sheet 
\*===========================================================================*/
char* ProTestDrwGetPlotSize (ProPlotPaperSize type)
{
    switch (type)
    {
       case A_SIZE_PLOT         : return (char*)"A";
       case B_SIZE_PLOT         : return (char*)"B";
       case C_SIZE_PLOT         : return (char*)"C";
       case D_SIZE_PLOT         : return (char*)"D";
       case E_SIZE_PLOT         : return (char*)"E";
       case A4_SIZE_PLOT        : return (char*)"A4";
       case A3_SIZE_PLOT        : return (char*)"A3";
       case A2_SIZE_PLOT        : return (char*)"A2";
       case A1_SIZE_PLOT        : return (char*)"A1";
       case A0_SIZE_PLOT        : return (char*)"A0";
       case F_SIZE_PLOT         : return (char*)"F";
       case VARIABLE_SIZE_PLOT  : return (char*)"VARIABLE SIZE";
       default                  : return (char*)"Unknown";
    }
}

/*===========================================================================*\
  Function : ProTestDrwGetSheetOrient
  Purpose  : To get orientation of sheet 
\*===========================================================================*/
char* ProTestDrwGetSheetOrient (ProSheetOrientation orient)
{
    switch (orient)
    {
       case PRO_ORIENTATION_UNDEFINED  : return (char*)"Undefined";
       case PRO_ORIENTATION_LANDSCAPE   : return (char*)"Landscape";
       case PRO_ORIENTATION_PORTRAIT   : return (char*)"Portrait";
       default  : return (char*)"Unknown";
    }
}

/*===========================================================================*\
  FUNCTION: ProTestDrawingInfo
  PURPOSE:  
\*===========================================================================*/
ProError ProTestDrawingInfo ()
{
    char                    file_name [PRO_PATH_SIZE+1];
    int                     n_sheets, i, num;
    ProError                status;
    ProTestViewVisitData    visit_data ={NULL, 0};
    FILE                   *info_file  = NULL;
    ProPath                 w_path;
    ProDrawing              drawing;
    ProPlotPaperSize        size_type;
    double                  width;
    double                  height;
    ProUnititem             units;
    char                    unit_name [PRO_NAME_SIZE];
    ProSheetOrientation     orientation;
    ProSolid                *solids    = NULL;
    ProView                 *views     = NULL;
    ProDwgtable             *tables    = NULL;

    status = ProMdlCurrentGet ((ProMdl*)&drawing);

    ProUtilMsgPrint ("gen", "TEST %0s", "Enter name of file:");
    status = ProMessageStringRead (PRO_PATH_SIZE, w_path);
    
    if (status != PRO_TK_NO_ERROR)
        return PRO_TK_GENERAL_ERROR;
    
    ProWstringToString (file_name, w_path);

    if ((info_file=PTApplsUnicodeFopen(file_name, "w")) == NULL)
    {
        ProTKPrintf ("Cannot open output file.\n");
        return (PRO_TK_GENERAL_ERROR);
    }
    
    visit_data.fp = info_file;
    visit_data.drawing = drawing;

    ProTKFprintf (info_file,
        "-------------------Drawing information------------------\n\n");

/*--------------------------------------------------------------------*\
    Sheets
\*--------------------------------------------------------------------*/
    ProTKFprintf(info_file, "Sheets:\n");
    status = ProDrawingSheetsCount (drawing, &n_sheets);
    TEST_CALL_REPORT ("ProDrawingSheetsCount()", "ProTestDrawingInfo()",
        status, status!=PRO_TK_NO_ERROR);
    
    for (i=1; i < n_sheets + 1; i++)
    {
        status = ProDrawingSheetSizeGet (drawing, i, &size_type, 
					 &width, &height);
        TEST_CALL_REPORT ("ProDrawingSheetSizeGet()",
            "ProTestDrawingInfo()", status, status != PRO_TK_NO_ERROR);

	status = ProDrawingSheetUnitsGet (drawing, i, &units);
        TEST_CALL_REPORT ("ProDrawingSheetUnitsGet()",
            "ProTestDrawingInfo()", status, status != PRO_TK_NO_ERROR);

	status = ProDrawingSheetOrientationGet (drawing, i, &orientation);
        TEST_CALL_REPORT ("ProDrawingSheetOrientationGet()",
            "ProTestDrawingInfo()", status, status != PRO_TK_NO_ERROR);	
    
	ProWstringToString (unit_name, units.name);

        ProTKFprintf(info_file, 
            "[%d] DwgSize: %s; width:%lf; height:%lf; units:%s; orientation: %s\n",
            i, 
            ProTestDrwGetPlotSize (size_type),
            width, 
            height, 
            unit_name, 
            ProTestDrwGetSheetOrient (orientation));
    }

/*--------------------------------------------------------------------*\
    Solids
\*--------------------------------------------------------------------*/
    ProTKFprintf(info_file, "Solids:\n");
    visit_data.count = 0;
#if 0
    status = ProDrawingSolidsVisit (drawing,
                (ProSolidVisitAction)ProTestSolidVisitAction,
                (ProSolidFilterAction)ProTestSolidFilterAction,
                (ProAppData)&visit_data);
    TEST_CALL_REPORT ("ProDrawingSolidsVisit()",
        "ProTestDrawingInfo()", status, status!=PRO_TK_NO_ERROR);
#else
    status = ProDrawingSolidsCollect (drawing, &solids);
    TEST_CALL_REPORT ("ProDrawingSolidsCollect()", "ProTestDrawingInfo()",
        status, status!=PRO_TK_NO_ERROR);
        
    if (status == PRO_TK_NO_ERROR)
    {
        /*status!=PRO_TK_GENERAL_ERROR until solids cotrrupt.*/
        
        status = ProArraySizeGet ((ProArray)solids, &num);
        TEST_CALL_REPORT ("ProArraySizeGet()", "ProTestDrawingInfo()",
            status, status!=PRO_TK_NO_ERROR && status!=PRO_TK_BAD_INPUTS);
            
        for (i=0; i<num; i++)
        {
            status = ProTestSolidVisitAction (
                        solids[i], PRO_TK_NO_ERROR, &visit_data);
        }
        
        status = ProArrayFree ((ProArray*)&solids);
        TEST_CALL_REPORT ("ProArrayFree()", "ProTestDrawingInfo()",
            status, status!=PRO_TK_NO_ERROR && status!=PRO_TK_BAD_INPUTS);
    }
#endif
    
/*--------------------------------------------------------------------*\
    Views
\*--------------------------------------------------------------------*/
    ProTKFprintf(info_file, "Views:\n");

    visit_data.count = 0;
#if 0
    status = ProDrawingViewVisit (drawing,
                (ProViewVisitAction)ProTestViewVisitAction,
                (ProViewFilterAction)ProTestViewFilterAction,
                (ProAppData)&visit_data);
    TEST_CALL_REPORT ("ProDrawingViewVisit()", "ProTestDrawingInfo()",
        status, status!=PRO_TK_NO_ERROR);
#else
    status = ProDrawingViewsCollect (drawing, &views);
    TEST_CALL_REPORT ("ProDrawingViewsCollect()", "ProTestDrawingInfo()",
        status, status!=PRO_TK_NO_ERROR);
        
    if (status == PRO_TK_NO_ERROR)
    {
        status = ProArraySizeGet ((ProArray)views, &num);
        TEST_CALL_REPORT ("ProArraySizeGet()", "ProTestDrawingInfo()",
            status, status!=PRO_TK_NO_ERROR);
            
        for (i=0; i<num; i++)
        {
            status = ProTestViewVisitAction (drawing,
                        views[i], PRO_TK_NO_ERROR, &visit_data);
        }
        
        status = ProArrayFree ((ProArray*)&views);
        TEST_CALL_REPORT ("ProArrayFree()", "ProTestDrawingInfo()",
            status, status!=PRO_TK_NO_ERROR);
    }
#endif

/*--------------------------------------------------------------------*\
    Tables
\*--------------------------------------------------------------------*/
    ProTKFprintf(info_file,"Tables:\n");
    visit_data.count = 0;
#if 0
    status = ProDrawingTableVisit (drawing,
                (ProDwgtableVisitAction)ProTestDwgtableVisitAction,
                (ProDwgtableFilterAction)ProTestDwgtableFilterAction,
                (ProAppData)&visit_data);
    TEST_CALL_REPORT ("ProDrawingTableVisit()", "ProTestDrawingInfo()",
        status, status!=PRO_TK_NO_ERROR);
#else
    status = ProDrawingTablesCollect (drawing, &tables);
    TEST_CALL_REPORT ("ProDrawingTablesCollect()", "ProTestDrawingInfo()",
        status, status!=PRO_TK_NO_ERROR && status!=PRO_TK_E_NOT_FOUND);
        
    if (status == PRO_TK_NO_ERROR)
    {
        status = ProArraySizeGet ((ProArray)tables, &num);
        TEST_CALL_REPORT ("ProArraySizeGet()", "ProTestDrawingInfo()",
            status, status!=PRO_TK_NO_ERROR);
            
        for (i=0; i<num; i++)
        {
            status = ProTestDwgtableVisitAction (
                        &tables[i], PRO_TK_NO_ERROR, &visit_data);
        }
        
        status = ProArrayFree ((ProArray*)&tables);
        TEST_CALL_REPORT ("ProArrayFree()", "ProTestDrawingInfo()",
            status, status!=PRO_TK_NO_ERROR);
    }
#endif
    ProTKFprintf (info_file,
        "--------------------------------------------------------\n");

    fclose(info_file);

#if 0
    status = ProInfoWindowDisplay (
                ProStringToWstring(wstr, file_name), NULL, NULL);
    TEST_CALL_REPORT ("ProInfoWindowDisplay()", "ProTestDrawingInfo()",
        status, status!=PRO_TK_NO_ERROR);
#endif
    return(PRO_TK_NO_ERROR);
}