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


#include <ProToolkit.h>
#include <ProDrawing.h>
#include <ProDtlitem.h>
#include <ProDtlsymdef.h>
#include <ProDtlsyminst.h>
#include <ProDtlnote.h>
#include <ProWindows.h>
#include <ProMessage.h>
#include <ProMdl.h>
#include <ProModelitem.h>

#include "TestError.h"
#include "UtilMessage.h"
#include "UtilString.h"
#include "UtilNames.h"
#include <ProTKRunTime.h>
#include <PTApplsUnicodeUtils.h>

#define BOOL_TO_STR(a)  (a)?("TRUE"):("FALSE")

/*=========================================================================*\
    Function:	ProTestSymDefInfoAttach()
    Purpose:    Print info about all attache from symdata
    Returns:	PRO_TK_NO_ERROR if success;
\*=========================================================================*/
ProError ProTestSymDefInfoAttach(FILE *fp, ProDtlsymdefdata symdata)
{
    ProError error;
    int n_attache;
    ProDtlsymdefattach *attaches;
    double entity_parameter;
    ProVector location;
    int entity_id, n;
    ProCharLine astr;
    ProDtlsymdefattachType type;

    /*-------------------------------------------------------------*\
        Check data
    \*-------------------------------------------------------------*/
    if((fp==NULL)||(symdata==NULL))
        return(PRO_TK_BAD_INPUTS);

    error = ProDtlsymdefdataAttachGet(symdata,	&attaches);
    TEST_CALL_REPORT ("ProDtlsymdefdataAttachGet()",
                      "ProTestSymDefInfoAttach()", error, error != PRO_TK_NO_ERROR);

    if(error!=PRO_TK_NO_ERROR)
        return(PRO_TK_GENERAL_ERROR);

    /*-------------------------------------------------------------*\
        Calculate attaches count
    \*-------------------------------------------------------------*/
    error = ProArraySizeGet((ProArray)attaches, &n_attache);
    TEST_CALL_REPORT ("ProArraySizeGet()",
                      "ProTestSymDefInfoAttach()", error, error != PRO_TK_NO_ERROR);

    if(error!=PRO_TK_NO_ERROR)
        n_attache = 0;

    ProTKFprintf(fp,"\t\tAttaches count:%d\n", n_attache);
    if(n_attache>0)
        for(n=0; n<n_attache; n++)
        {
            /*-------------------------------------------------------------*\
            	Get attaches information from current symdef
            \*-------------------------------------------------------------*/
            error = ProDtlsymdefattachGet(attaches[n],
                                          &type, &entity_id, &entity_parameter, location);
            TEST_CALL_REPORT ("ProDtlsymdefattachGet()",
                              "ProTestSymDefInfoAttach()", error, error != PRO_TK_NO_ERROR);

            if(error!=PRO_TK_NO_ERROR)
                continue;
            /*-------------------------------------------------------------*\
            	Print attaches type
            \*-------------------------------------------------------------*/
            switch(type)
            {
            case PROSYMDEFATTACHTYPE_FREE :
                ProTKSprintf(astr,"%s","Free");
                break;
            case PROSYMDEFATTACHTYPE_LEFT_LEADER :
                ProTKSprintf(astr,"%s","Left Leader");
                break;
            case PROSYMDEFATTACHTYPE_RIGHT_LEADER :
                ProTKSprintf(astr,"%s","Right Leader");
                break;
            case PROSYMDEFATTACHTYPE_RADIAL_LEADER :
                ProTKSprintf(astr,"%s","Radial Leader");
                break;
            case PROSYMDEFATTACHTYPE_ON_ITEM :
                ProTKSprintf(astr,"%s","On item");
                break;
            case PROSYMDEFATTACHTYPE_NORM_ITEM :
                ProTKSprintf(astr,"%s","Normal item");
                break;
            default:
                ProTKSprintf(astr,"%s","None");
            }/* switch */

            /*-------------------------------------------------------------*\
            	Print attache entity information
            \*-------------------------------------------------------------*/
            if(type != PROSYMDEFATTACHTYPE_FREE)
            {
                ProTKFprintf(fp,"\t\t\t[%d] Attache type: %s\n",n, astr);
                ProTKFprintf(fp,"\t\t\tEntity id: %d \n", entity_id);
                ProTKFprintf(fp,"\t\t\tParameter: %3.3f\n", entity_parameter);
                ProTKFprintf(fp,"\t\t\tLocation : (%3.3f, %3.3f, %3.3f)\n",
                        location[0], location[1], location[2]);
            }
        }/* for n */

    /*-------------------------------------------------------------*\
    	Free attaches array	
    \*-------------------------------------------------------------*/
    if(attaches!=NULL)
    {
        error = ProArrayFree((ProArray*)&attaches);
        TEST_CALL_REPORT ("ProArrayFree()",
                          "ProTestSymDefInfoAttach()", error, error != PRO_TK_NO_ERROR);
    }

    return(PRO_TK_NO_ERROR);
}

/*=========================================================================*\
    Function:	ProTestSymDefInfoNote()
    Purpose:    Print info about all notes from symdata
    Returns:	PRO_TK_NO_ERROR if success;
\*=========================================================================*/
ProError ProTestSymDefInfoNote(FILE *fp, ProDrawing drawing, int sheet,
                               ProDtlsymdef *symbol, ProDtlsymdefdata symdata)
{
    ProError error;
    ProCharLine astr;
    ProLine     wline;
    ProDtlnote *notes;
    int n_notes, note_id,
    n_line, n_text,
    k, m, l;
    ProDtlnotedata notedata;
    ProDtlnoteline *note_lines;
    ProDtlnotetext *note_text;

    /*-------------------------------------------------------------*\
    	Check input 
    \*-------------------------------------------------------------*/
    if((drawing==NULL)||(fp==NULL)||(symbol==NULL)||(symdata==NULL))
        return(PRO_TK_BAD_INPUTS);

    /*-------------------------------------------------------------*\
    	Collect all notes for current symdef
    \*-------------------------------------------------------------*/
    error = ProDrawingDtlnotesCollect(drawing, symbol, sheet, &notes);
    TEST_CALL_REPORT ("ProDrawingDtlnotesCollect()",
                      "ProTestSymDefInfoNote()", error, error != PRO_TK_NO_ERROR &&
                      error != PRO_TK_E_NOT_FOUND);

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

    /*-------------------------------------------------------------*\
    	Calculate notes count
    \*-------------------------------------------------------------*/

    error = ProArraySizeGet((ProArray)notes, &n_notes);
    TEST_CALL_REPORT ("ProArraySizeGet()",
                      "ProTestSymDefInfoNote()", error, error != PRO_TK_NO_ERROR);

    if(error!=PRO_TK_NO_ERROR)
        n_notes = 0;

    /*-------------------------------------------------------------*\
    	Print info for all notes in current symdef
    \*-------------------------------------------------------------*/
    if(n_notes>0)
    {
        ProTKFprintf(fp,"\t\t\t\tNote count: %d\n",n_notes);
        for(k=0; k<n_notes; k++)
        {
            error = ProDtlnoteDataGet(&notes[k], symbol,
                                      PRODISPMODE_SYMBOLIC, &notedata);
            TEST_CALL_REPORT ("ProDtlnoteDataGet()",
                              "ProTestSymDefInfoNote()", error, error != PRO_TK_NO_ERROR);

            error = ProDtlnotedataIdGet(notedata, &note_id);
            TEST_CALL_REPORT ("ProDtlnotedataIdGet()",
                              "ProTestSymDefInfoNote()", error, error != PRO_TK_NO_ERROR);
            /*-------------------------------------------------------------*\
            	    Collect all lines in the current note
            \*-------------------------------------------------------------*/
            error = ProDtlnotedataLinesCollect(notedata, &note_lines);
            TEST_CALL_REPORT ("ProDtlnotedataLinesCollect()",
                "ProTestSymDefInfoNote()", error, 
                error != PRO_TK_NO_ERROR && error != PRO_TK_E_NOT_FOUND);
            error = ProArraySizeGet((ProArray)note_lines, &n_line);
            TEST_CALL_REPORT ("ProArraySizeGet()",
                              "ProTestSymDefInfoNote()", error, error != PRO_TK_NO_ERROR);

            if(error==PRO_TK_NO_ERROR)
            {
                ProTKFprintf(fp,"\t\t\t\t\t[%d] lines count: %d\n",k, n_line);
                for(l=0;l<n_line; l++)
                {
                    /*-------------------------------------------------------------*\
                    		Collect all texts in the current line
                    \*-------------------------------------------------------------*/
                    error = ProDtlnotelineTextsCollect(note_lines[l],
                                                       &note_text);
                    TEST_CALL_REPORT ("ProDtlnotelineTextsCollect()",
                        "ProTestSymDefInfoNote()", error, 
                        error != PRO_TK_NO_ERROR && error != PRO_TK_E_NOT_FOUND);
                    error = ProArraySizeGet((ProArray)note_lines, &n_text);
                    if(error==PRO_TK_NO_ERROR)
                    {
                        for(m=0; m<n_text; m++)
                        {
                            /*-------------------------------------------------------------*\
                            		    Collect all strings in the current text
                            \*-------------------------------------------------------------*/
                            if (note_text[m] != NULL)
                            {
                                error = ProDtlnotetextStringGet(note_text[m], wline);
                                TEST_CALL_REPORT ("ProDtlnotetextStringGet()",
                                              "ProTestSymDefInfoNote()", error, error != PRO_TK_NO_ERROR);

                                if(error==PRO_TK_NO_ERROR)
                                    ProTKFprintf(fp,"\t\t\t\t\t\t%s\n",ProWstringToString(astr, wline));
                            }
                        } /* for m*/

                        /*-------------------------------------------------------------*\
                        		Free note_text array
                        \*-------------------------------------------------------------*/
                        for (m=0; m<n_text; m++)
                        {
                            if (note_text[m] != NULL)
                            {
                                error = ProDtlnotetextFree (note_text[m]);
                                TEST_CALL_REPORT("ProDtlnotetextFree()",
                                             "ProTestDtlNoteInfo()", error, error != PRO_TK_NO_ERROR);
                            }
                        }
                        if(note_text!=NULL)
                        {
                            error = ProArrayFree((ProArray*)&note_text);
                            TEST_CALL_REPORT ("ProArrayFree()",
                                              "ProTestSymDefInfoNote()", error, error != PRO_TK_NO_ERROR);
                        }
                    }
                }/* for l*/
                /*-------------------------------------------------------------*\
                		Free note_lines array
                \*-------------------------------------------------------------*/
                for (l=0;l< n_line; l++)
                {
                    error = ProDtlnotelineFree (note_lines[l]);
                    TEST_CALL_REPORT("ProDtlnotelineFree()",
                                     "ProTestDtlNoteInfo()", error, error != PRO_TK_NO_ERROR);
                }
                if(note_lines!=NULL)
                {
                    error = ProArrayFree((ProArray*)&note_lines);
                    TEST_CALL_REPORT ("ProArrayFree()",
                                      "ProTestSymDefInfoNote()", error, error != PRO_TK_NO_ERROR);
                }
            }
        }/* for k*/
    }/* if (n_notes>0) */

    /*-------------------------------------------------------------*\
    		Free notes array
    \*-------------------------------------------------------------*/

    if(notes!=NULL)
    {
        error = ProArrayFree((ProArray*)&notes);
        TEST_CALL_REPORT ("ProArrayFree()",
                          "ProTestSymDefInfo()", error, error != PRO_TK_NO_ERROR);
        notes = NULL;
    }

    return(PRO_TK_NO_ERROR);
}

ProError ProTestSymDefInfo()
{
    ProError error;
    FILE *fp=NULL;
    ProPath wstr;
    ProCharLine astr;
    char file_name[] = "DrwSymDef.info";
    ProDrawing drawing;
    int i, j;
    int n_symdef, n_sheets;
    int entity, line, text;
    int id;
    ProDtlsymdef *symdefs;
    ProDtlsymdefdata symdata;
    ProBoolean elbow, angle_fixed;
    double height;
    ProDtlsymdefdataHeighttype type;
    int	current_sheet;

    /*-------------------------------------------------------------*\
       Get handle to the current drawing
    \*-------------------------------------------------------------*/
    error = ProMdlCurrentGet((ProMdl*)&drawing);
    TEST_CALL_REPORT ("ProMdlCurrentGet()",
                      "ProTestSymDefInfo()", error, error != PRO_TK_NO_ERROR);

    if(error!=PRO_TK_NO_ERROR)
        return(PRO_TK_GENERAL_ERROR);
    /*-------------------------------------------------------------*\
        Open file for print symdef information 
    \*-------------------------------------------------------------*/
    if ((fp = PTApplsUnicodeFopen(file_name, "w")) == NULL)
    {
        ProTKPrintf("Cannot open output file\n");
        return (PRO_TK_GENERAL_ERROR);
    }

    /*-------------------------------------------------------------*\
        Get sheets count in the current drawing
    \*-------------------------------------------------------------*/
    error = ProDrawingSheetsCount(drawing, &n_sheets);
    TEST_CALL_REPORT ("ProDrawingSheetsCount()",
                      "ProTestSymDefInfo()", error, error != PRO_TK_NO_ERROR);

    /*-------------------------------------------------------------*\
	Store current sheet id
    \*-------------------------------------------------------------*/
    error = ProDrawingCurrentSheetGet( drawing, &current_sheet );
    TEST_CALL_REPORT ("ProDrawingCurrentSheetGet()",
	"ProTestSymDefInfo()", error, error != PRO_TK_NO_ERROR);

    ProTKFprintf(fp,"Sheets count: %d\n", n_sheets);
    for(i=0; i<n_sheets; i++)
    {
	error = ProDrawingCurrentSheetSet( drawing, i );
	TEST_CALL_REPORT ("ProDrawingCurrentSheetSet()",
	    "ProTestSymDefInfo()", error, error != PRO_TK_NO_ERROR);

        /*-------------------------------------------------------------*\
        	Collect all symdefs in the current sheet
        \*-------------------------------------------------------------*/
        error = ProDrawingDtlsymdefsCollect(drawing, &symdefs);
        TEST_CALL_REPORT ("ProDrawingDtlsymdefsCollect()",
                          "ProTestSymDefInfo()", error, error != PRO_TK_NO_ERROR);

        if(error!=PRO_TK_NO_ERROR)
            continue;

        error = ProArraySizeGet((ProArray)symdefs, &n_symdef);
        TEST_CALL_REPORT ("ProArraySizeGet()",
                          "ProTestSymDefInfo()", error, error != PRO_TK_NO_ERROR);

        if((error!=PRO_TK_NO_ERROR)||(n_symdef<=0))
        {
            error = ProArrayFree((ProArray*)&symdefs);
            TEST_CALL_REPORT ("ProArrayFree()",
                              "ProTestSymDefInfo()", error, error != PRO_TK_NO_ERROR);
            continue;
        }
        /*-------------------------------------------------------------*\
        	Print symdef information for all sheets 
        	in current drawing
        \*-------------------------------------------------------------*/
        ProTKFprintf(fp,"\tSheet %d, symdef count: %d\n", i, n_symdef);
        for(j=0; j<n_symdef; j++)
        {
            /*-------------------------------------------------------------*\
            	    Get symdef data for current symdef
            \*-------------------------------------------------------------*/
            error = ProDtlsymdefDataGet(&symdefs[j], &symdata);
            TEST_CALL_REPORT ("ProDtlsymdefDataGet()",
                              "ProTestSymDefInfo()", error, error != PRO_TK_NO_ERROR);

            if(error!=PRO_TK_NO_ERROR)
                continue;

            error = ProDtlsymdefdataIdGet(symdata, &id);
            TEST_CALL_REPORT ("ProDtlsymdefdataIdGet()",
                              "ProTestSymDefInfo()", error, error != PRO_TK_NO_ERROR);

            ProTKFprintf(fp,"\t\t[%d] Symdef id: %d\n", j, id);
#if 0
            /*-------------------------------------------------------------*\
            	    Get symdef name
            \*-------------------------------------------------------------*/
            error = ProDtlsymdefdataPathGet(symdata, wstr);
            TEST_CALL_REPORT ("ProDtlsymdefdataPathGet()",
                              "ProTestSymDefInfo()", error, error != PRO_TK_NO_ERROR);
#endif

            ProTKFprintf(fp,"\t\t\tSymdef path: %s\n",ProWstringToString(astr, wstr));
            /*-------------------------------------------------------------*\
            	    Get symdef Elbow flag
            \*-------------------------------------------------------------*/
            error = ProDtlsymdefdataElbowGet(symdata, &elbow);
            TEST_CALL_REPORT ("ProDtlsymdefdataElbowGet()",
                              "ProTestSymDefInfo()", error, error != PRO_TK_NO_ERROR);

            ProTKFprintf(fp,"\t\t\tElbow : %s\n", BOOL_TO_STR(elbow));
            /*-------------------------------------------------------------*\
            	    Get symdef text angle property.
            \*-------------------------------------------------------------*/
            error = ProDtlsymdefdataTextangfixedGet(symdata, &angle_fixed);
            TEST_CALL_REPORT ("ProDtlsymdefdataTextangfixedGet()",
                              "ProTestSymDefInfo()", error, error != PRO_TK_NO_ERROR);

            ProTKFprintf(fp,"\t\t\tText angle fixed: %s\n", BOOL_TO_STR(angle_fixed));

            /*-------------------------------------------------------------*\
            	    Get symdef height type.
            \*-------------------------------------------------------------*/
            error = ProDtlsymdefdataHeighttypeGet(symdata, &type);
            TEST_CALL_REPORT ("ProDtlsymdefdataHeighttypeGet()",
                              "ProTestSymDefInfo()", error, error != PRO_TK_NO_ERROR);

            ProTKFprintf(fp,"\t\t\tHeight type: %s\n",
                    (type==PRODTLSYMDEFHGHTTYPE_FIXED)?("Fixed"):
                    ((type==PRODTLSYMDEFHGHTTYPE_VARIABLE)?("Variable"):("Text related")));

            /*-------------------------------------------------------------*\
            	    Get symdef height 
            \*-------------------------------------------------------------*/	
            error = ProDtlsymdefdataScaledheightGet(symdata,&height);
            TEST_CALL_REPORT ("ProDtlsymdefdataScaledheightGet()",
                              "ProTestSymDefInfo()", error, error != PRO_TK_NO_ERROR);

            ProTKFprintf(fp,"\t\t\tHeight: %3.3f\n", height);

            if(type==PRODTLSYMDEFHGHTTYPE_TEXTRELATED)
            {

                /*-------------------------------------------------------------*\
                	    Get symdef height type - text related 
                	    then print information about related note.
                \*-------------------------------------------------------------*/
                error = ProDtlsymdefdataTextrefGet(symdata, &entity, &line, &text);
                TEST_CALL_REPORT ("ProDtlsymdefdataTextrefGet()",
                                  "ProTestSymDefInfo()", error, error != PRO_TK_NO_ERROR);
                if(error==PRO_TK_NO_ERROR)
                {
                    ProTKFprintf(fp, "\t\t\tRef text entity id : %d\n", entity);
                    ProTKFprintf(fp, "\t\t\tRef text line      : %d\n", line);
                    ProTKFprintf(fp, "\t\t\tRef text index     : %d\n", text);
                }
            }
            /*-------------------------------------------------------------*\
            	   Print information about all notes in current symdef
            \*-------------------------------------------------------------*/
            error = ProTestSymDefInfoNote(fp, drawing, i, &symdefs[j], symdata);

            /*-------------------------------------------------------------*\
            	   Print information about all attaches 
            	   in the current symdef
            \*-------------------------------------------------------------*/
            error = ProTestSymDefInfoAttach(fp, symdata);

            ProTKFprintf(fp,"---------------------------------------------------------------------\n");
        }

        if(symdefs!=NULL)
        {
            error = ProArrayFree((ProArray*)&symdefs);
            TEST_CALL_REPORT ("ProArrayFree()",
                              "ProTestSymDefInfo()", error, error != PRO_TK_NO_ERROR);
        }
    }

    /*-------------------------------------------------------------*\
	Restore current sheet
    \*-------------------------------------------------------------*/
    error = ProDrawingCurrentSheetSet( drawing, current_sheet );
    TEST_CALL_REPORT ("ProDrawingCurrentSheetSet()", "ProTestSymDefInfo()", 
	error, error != PRO_TK_NO_ERROR);

    /*-------------------------------------------------------------*\
    	   Close file and
    	   show it in the information window.
    \*-------------------------------------------------------------*/
    fclose(fp);
    error = ProInfoWindowDisplay(ProStringToWstring(wstr,file_name), NULL, NULL);
    TEST_CALL_REPORT ("ProInfoWindowDisplay()",
                      "ProTestSymDefInfo()", error, error != PRO_TK_NO_ERROR);

    return(PRO_TK_NO_ERROR);
}