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


/*--------------------------------------------------------------------*\
Pro/TOOLKIT includes
\*--------------------------------------------------------------------*/
#include <ProToolkit.h>
#include <ProAnalysis.h>
#include <ProModelitem.h>
#include <ProMessage.h>
#include <ProArray.h>
#include <ProPoint.h>
#include <ProDtmPnt.h>
#include <ProUtil.h>

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

#include "UtilMath.h"

/*====================================================================*\
FUNCTION : ProTestCompCurveUiAction()
PURPOSE  : Callback for UI action of analysis feature
\*====================================================================*/
ProError ProTestCompCurveUiAction (
    ProAnalysis analysis)
{
    CompCurvedata_t *data;
    ProError err = PRO_TK_NO_ERROR;
    ProSelection *sel;
    int n_sel;
    ProModelitem model_item;
    ProCurve curve;
    ProVector origin, x, y;

    TEST_CALL_REPORT ("ProAnalysisUiAction()", 
        "ProTestCompCurveUiAction()", err, err != PRO_TK_NO_ERROR);

/*--------------------------------------------------------------------*\
    Get the data pointer from the analysis
\*--------------------------------------------------------------------*/
    err = ProAnalysisInfoGet (analysis, (ProAppData*)&data);
    TEST_CALL_REPORT ("ProAnalysisInfoGet()", 
        "ProTestCompCurveUiAction()", err, err != PRO_TK_NO_ERROR);
    if (err != PRO_TK_NO_ERROR)
	return(PRO_TK_USER_ABORT);

    ProArrayAlloc (0, sizeof (ProModelitem), 1, 
        (ProArray*)&data->curves);

    ProMessageDisplay (msgfil, (char *)"USER Select a curve");

/*--------------------------------------------------------------------*\
    Collect curves for future composite curve
\*--------------------------------------------------------------------*/
    while (1)
    {
        if (ProSelect ((char *)"curve", 1, NULL, NULL, NULL, NULL, &sel, &n_sel) 
            != PRO_TK_NO_ERROR || n_sel < 1)
            break;

        err = ProSelectionModelitemGet(sel[0], &model_item);
        TEST_CALL_REPORT ("ProSelectionModelitemGet()", 
            "ProTestCompCurveUiAction()", err, err != PRO_TK_NO_ERROR);

        if (model_item.type != PRO_CURVE || err != PRO_TK_NO_ERROR)
	    continue;

        err = ProArrayObjectAdd ((ProArray*)&data->curves, PRO_VALUE_UNUSED,
            1, &model_item);
        TEST_CALL_REPORT ("ProArrayObjectAdd()", 
            "ProTestCompCurveUiAction()", err, err != PRO_TK_NO_ERROR);
    }

    err = ProArraySizeGet (data->curves, &n_sel);
    if (n_sel < 1 || err != PRO_TK_NO_ERROR)
        return PRO_TK_USER_ABORT;

    return(PRO_TK_NO_ERROR);
}

/*====================================================================*\
FUNCTION : ProTestCompCurveDimsAction()
PURPOSE  :
\*====================================================================*/
ProError ProTestCompCurveDimsAction(
    ProAnalysis analysis,
    double **dims)
{
    ProError err = PRO_TK_NO_ERROR;

    TEST_CALL_REPORT ("ProAnalysisDimsAction()", 
        "ProTestCompCurveDimsAction()", err, err != PRO_TK_NO_ERROR);

/*--------------------------------------------------------------------*\
    No dimensions 
\*--------------------------------------------------------------------*/
 
    return(PRO_TK_NO_ERROR);
}

/*====================================================================*\
FUNCTION : ProTestCompCurveInfoallocAction()
PURPOSE  : Callback to allocate application data needed to describe
		the analysis feature
\*====================================================================*/
ProError ProTestCompCurveInfoallocAction(
    ProAnalysis analysis)
{
    CompCurvedata_t *data;
    ProError err = PRO_TK_NO_ERROR;

    TEST_CALL_REPORT ("ProAnalysisInfoallocAction()", 
        "ProTestCompCurveInfoallocAction()", err, err != PRO_TK_NO_ERROR);
/*--------------------------------------------------------------------*\
    Allocate a data structure
\*--------------------------------------------------------------------*/
    data = (CompCurvedata_t*)calloc(1, sizeof(CompCurvedata_t));
    if (data == NULL)
        return PRO_TK_USER_ABORT;

/*--------------------------------------------------------------------*\
    Put the data pointer into the analysis
\*--------------------------------------------------------------------*/
    err = ProAnalysisInfoSet(analysis, data);
    TEST_CALL_REPORT ("ProAnalysisInfoSet()", 
        "ProTestCompCurveInfoallocAction()", err, err != PRO_TK_NO_ERROR);

    return(PRO_TK_NO_ERROR);
}

/*====================================================================*\
FUNCTION : ProTestCompCurveInfofreeAction()
PURPOSE  : Callback to free the application data
\*====================================================================*/
ProError ProTestCompCurveInfofreeAction(
    ProAnalysis analysis)
{
    CompCurvedata_t *data;
    ProError err = PRO_TK_NO_ERROR;

    TEST_CALL_REPORT ("ProAnalysisInfofreeAction()", 
        "ProTestCompCurveInfofreeAction()", err, err != PRO_TK_NO_ERROR);
/*--------------------------------------------------------------------*\
    Get the data pointer from the analysis
\*--------------------------------------------------------------------*/
    err = ProAnalysisInfoGet (analysis, (ProAppData*)&data);
    TEST_CALL_REPORT ("ProAnalysisInfoGet()", 
        "ProTestCompCurveInfofreeAction()", err, err != PRO_TK_NO_ERROR);
    if (err != PRO_TK_NO_ERROR)
        return(PRO_TK_GENERAL_ERROR);

/*--------------------------------------------------------------------*\
    Free the data
\*--------------------------------------------------------------------*/
    free (data);

/*--------------------------------------------------------------------*\
    Set the data pointer in the analysis to NULL
\*--------------------------------------------------------------------*/
    err = ProAnalysisInfoSet (analysis, NULL);
    TEST_CALL_REPORT ("ProAnalysisInfoSet()", 
        "ProTestCompCurveInfofreeAction()", err, err != PRO_TK_NO_ERROR);

    return(PRO_TK_NO_ERROR);
}

/*====================================================================*\
FUNCTION : ProTestCompCurveCompcheckAction()
PURPOSE  : Callback to tell Pro/E whether computation can be performed
		in this analysis feature
\*====================================================================*/
ProError ProTestCompCurveCompcheckAction(
    ProAnalysis analysis)
{
    ProError err = PRO_TK_NO_ERROR;

    TEST_CALL_REPORT ("ProAnalysisComputecheckAction()", 
        "ProTestCompCurveCompcheckAction()", err, err != PRO_TK_NO_ERROR);

    return (PRO_TK_NO_ERROR);
}

/*====================================================================*\
FUNCTION : ProTestCompCurveComputeAction()
PURPOSE  : Callback to perform the analysis feature computation
\*====================================================================*/
ProError ProTestCompCurveComputeAction(
    ProAnalysis analysis)
{
    ProError err = PRO_TK_NO_ERROR;
    ProGeomitem *curves;
    ProGeomitemdata *gdata;
    double *par_arr, double1, double2, double3;
    ProPoint3d *pnt_arr, point1, point2;
    ProVector *tan_arr, vector1, vector2;
    ProBoolean is_inactive;
    int c, p, n_curves, n_pnt;
    CompCurvedata_t *data;
    ProComponentCurvedata *component;

    TEST_CALL_REPORT ("ProAnalysisComputeAction()", 
        "ProTestCompCurveComputeAction()", err, err != PRO_TK_NO_ERROR);

/*--------------------------------------------------------------------*\
    Get the application data from the analysis
\*--------------------------------------------------------------------*/
    err = ProAnalysisInfoGet (analysis, (ProAppData*)&data);
    TEST_CALL_REPORT ("ProAnalysisInfoGet()", 
        "ProTestCompCurveComputeAction()", err, err != PRO_TK_NO_ERROR);
    if (err != PRO_TK_NO_ERROR)
	return(PRO_TK_GENERAL_ERROR);

    ProArraySizeGet (data->curves, &n_curves);
    
    err = ProArrayAlloc (0, sizeof(ProComponentCurvedata), 1, 
        (ProArray*)&data->components);
    for (c = 0; c < n_curves; c++)
    {
/*--------------------------------------------------------------------*\
        Get geometry of curve
\*--------------------------------------------------------------------*/
        err = ProGeomitemdataGet(&data->curves[c], &gdata);
        TEST_CALL_REPORT ("ProGeomitemdataGet()", 
            "ProTestCompCurveComputeAction()", err, 
            err != PRO_TK_NO_ERROR);

/*--------------------------------------------------------------------*\
        Allocate memory for curve component
\*--------------------------------------------------------------------*/
        err = ProComponentCurvedataAlloc (&component);
        TEST_CALL_REPORT ("ProComponentCurvedataAlloc()", 
            "ProTestCompCurveComputeAction()", err, 
            err != PRO_TK_NO_ERROR);

/*--------------------------------------------------------------------*\
        Initialize curve component
\*--------------------------------------------------------------------*/
        err = ProComponentCurvedataInit (gdata->data.p_curve_data, 
            PRO_CURVE_NO_FLIP, component);
        TEST_CALL_REPORT ("ProComponentCurvedataInit()", 
            "ProTestCompCurveComputeAction()", err, 
            err != PRO_TK_NO_ERROR);
        
/*--------------------------------------------------------------------*\
        Add curve component to array
\*--------------------------------------------------------------------*/
        err = ProArrayObjectAdd ((ProArray*)&data->components,
            PRO_VALUE_UNUSED, 1, component);
        TEST_CALL_REPORT ("ProArrayObjectAdd()",
            "ProTestCompCurveComputeAction()",
            err, err != PRO_TK_NO_ERROR);

        err = ProGeomitemdataFree(&gdata);
        TEST_CALL_REPORT ("ProGeomitemdataFree()",
            "ProTestCompCurveComputeAction()",
            err, err != PRO_TK_NO_ERROR);
    }   

    return(PRO_TK_NO_ERROR);
}

/*====================================================================*\
FUNCTION : ProTestCompCurveDisplayAction()
PURPOSE  : Callback to display the results of the analysis computation
\*====================================================================*/
ProError ProTestCompCurveDisplayAction(
    ProAnalysis analysis)
{
    ProError err = PRO_TK_NO_ERROR;

    TEST_CALL_REPORT ("ProAnalysisDisplayAction()", 
        "ProTestCompCurveDisplayAction()", err, err != PRO_TK_NO_ERROR);

    return(PRO_TK_NO_ERROR);
}

/*====================================================================*\
FUNCTION : ProTestCompCurveOutputAction()
PURPOSE  : Callback to write textual information about the result of
		the computation
\*====================================================================*/
ProError ProTestCompCurveOutputAction(
    ProAnalysis analysis,
    ProLine **lines)
{
    ProError err = PRO_TK_NO_ERROR;

    TEST_CALL_REPORT ("ProAnalysisOutputAction()", 
        "ProTestCompCurveOutputAction()", err, err != PRO_TK_NO_ERROR);
    return(PRO_TK_NO_ERROR);
}

/*====================================================================*\
FUNCTION : ProTestCompCurveSavecheckAction()
PURPOSE  : Callback to tell Pro/E whether the analysis application
		data can be saved
\*====================================================================*/
ProError ProTestCompCurveSavecheckAction(
    ProAnalysis analysis)
{
    ProError err = PRO_TK_NO_ERROR;
    
    TEST_CALL_REPORT ("ProAnalysisSavecheckAction()", 
        "ProTestCompCurveSavecheckAction()", err, err != PRO_TK_NO_ERROR);

    return (PRO_TK_NO_ERROR);
}

/*====================================================================*\
FUNCTION : ProTestCompCurveInfosaveAction()
PURPOSE  : Callback to tell Pro/E what element references are required
		by the analysis feature, and save the rest of the info
		to Ext Data
\*====================================================================*/
ProError ProTestCompCurveInfosaveAction(
    ProAnalysis analysis,
    ProFeature  *feature,
    ProSelection **references)
{
    ProError err = PRO_TK_NO_ERROR;
    CompCurvedata_t *data;
    ProSelection sel;
    int num, i;

    TEST_CALL_REPORT ("ProAnalysisInfosaveAction()", 
        "ProTestCompCurveInfosaveAction()", err, err != PRO_TK_NO_ERROR);

/*--------------------------------------------------------------------*\
    Get the application data from the analysis
\*--------------------------------------------------------------------*/
    err = ProAnalysisInfoGet (analysis, (ProAppData*)&data);
    TEST_CALL_REPORT ("ProAnalysisInfoGet()", 
        "ProTestCompCurveInfosaveAction()", err, err != PRO_TK_NO_ERROR);
    if (err != PRO_TK_NO_ERROR)
        return(PRO_TK_GENERAL_ERROR);

/*--------------------------------------------------------------------*\
    Save references
\*--------------------------------------------------------------------*/
    ProArraySizeGet (data->curves, &num);
    for (i = 0; i < num; i++)
    {
        err = ProSelectionAlloc (NULL, &data->curves[i], &sel);
        TEST_CALL_REPORT ("ProSelectionAlloc()", 
            "ProTestCompCurveInfosaveAction()", 
            err, err != PRO_TK_NO_ERROR);

        err = ProArrayObjectAdd((ProArray*)references, PRO_VALUE_UNUSED, 
            1, &sel);
        TEST_CALL_REPORT ("ProArrayObjectAdd()", 
            "ProTestCompCurveInfosaveAction()", err, 
            err != PRO_TK_NO_ERROR);
    }


    return(PRO_TK_NO_ERROR);
}

/*====================================================================*\
FUNCTION : ProTestCompCurveInforetrieveAction()
PURPOSE  : Callback to get the references Pro/E has stored with the
		analysis feature
\*====================================================================*/
ProError ProTestCompCurveInforetrieveAction(
    ProAnalysis analysis,
    ProFeature *feature,
    ProSelection *references)
{
    CompCurvedata_t *data;
    int num, i;
    ProError err = PRO_TK_NO_ERROR;

    TEST_CALL_REPORT ("ProAnalysisInforetrieveAction()", 
        "ProTestCompCurveInforetrieveAction()", 
        err, err != PRO_TK_NO_ERROR);

/*--------------------------------------------------------------------*\
    Get the data pointer from the analysis
\*--------------------------------------------------------------------*/
    err = ProAnalysisInfoGet (analysis, (ProAppData*)&data);
    TEST_CALL_REPORT ("ProAnalysisInfoGet()", 
        "ProTestCompCurveInforetrieveAction()", 
        err, err != PRO_TK_NO_ERROR);
    if (err != PRO_TK_NO_ERROR)
	return(PRO_TK_GENERAL_ERROR);

/*--------------------------------------------------------------------*\
    Retrieve references
\*--------------------------------------------------------------------*/
    ProArraySizeGet (references, &num);
    for (i = 0; i < num; i++)
    {
        err = ProSelectionModelitemGet(references[i], &data->curves[i]);
        TEST_CALL_REPORT ("ProSelectionModelitemGet()", 
            "ProTestCompCurveInforetrieveAction()", 
            err, err != PRO_TK_NO_ERROR);
    }

    return(PRO_TK_NO_ERROR);
}

/*====================================================================*\
FUNCTION : ProTestCompCurveInfocopyAction()
PURPOSE  : Copy information
\*====================================================================*/
ProError ProTestCompCurveInfocopyAction(
    ProAnalysis from,
    ProAnalysis to)
{
    CompCurvedata_t *fdata, *tdata;
    ProError err = PRO_TK_NO_ERROR;

    TEST_CALL_REPORT ("ProAnalysisInfocopyAction()", 
        "ProTestCompCurveInfocopyAction()", 
        err, err != PRO_TK_NO_ERROR);

/*--------------------------------------------------------------------*\
    Get the application data from the analyses
\*--------------------------------------------------------------------*/
    err = ProAnalysisInfoGet (from, (ProAppData*)&fdata);
    TEST_CALL_REPORT ("ProAnalysisInfoGet()", 
        "ProTestCompCurveInfocopyAction()", 
        err, err != PRO_TK_NO_ERROR);
    if (err != PRO_TK_NO_ERROR)
	return(PRO_TK_GENERAL_ERROR);
    
    err = ProAnalysisInfoGet (to,   (ProAppData*)&tdata);
     TEST_CALL_REPORT ("ProAnalysisInfoGet()", 
        "ProTestCompCurveInfocopyAction()", 
        err, err != PRO_TK_NO_ERROR);
    if (err != PRO_TK_NO_ERROR)
	return(PRO_TK_GENERAL_ERROR);

/*--------------------------------------------------------------------*\
    Copy the application-specific data (everything except references)
\*--------------------------------------------------------------------*/
    tdata->curves = fdata->curves;

    return(PRO_TK_NO_ERROR);
}

/*====================================================================*\
FUNCTION : ProTestCompCurveResultAction()
PURPOSE  : Callback to give Pro/E the feature parameters and geometry
		that the analysis feature must contain
\*====================================================================*/
ProError ProTestCompCurveResultAction(
    ProAnalysis analysis,
    ProBoolean names_only,
    ProAnalysisParameter **parameters,
    ProAnalysisGeomitem  **geometry)
{
    CompCurvedata_t *data;
    ProAnalysisGeomitem geomitem;
    ProAnalysisParameter param;
    ProError err = PRO_TK_NO_ERROR;
    int num, i, n_pnt, s;
    ProCurvedata *curve_data;
    ProCurveDir dir;

    TEST_CALL_REPORT ("ProAnalysisResultAction()", 
        "ProTestCompCurveResultAction()", 
        err, err != PRO_TK_NO_ERROR);

/*--------------------------------------------------------------------*\
    Get the application data from the analysis
\*--------------------------------------------------------------------*/
    err = ProAnalysisInfoGet (analysis, (ProAppData*)&data);
    TEST_CALL_REPORT ("ProAnalysisInfoGet()",
        "ProTestCompCurveResultAction()", err, err != PRO_TK_NO_ERROR);
    if (err != PRO_TK_NO_ERROR)
	return(PRO_TK_GENERAL_ERROR);

/*  CURVE */

    ProStringToWstring (geomitem.name,(char *)"COMP_CURVE");
    geomitem.create = PRO_B_TRUE;
    geomitem.type = PRO_ANALYSIS_COMP_CRV;

    if (!names_only)
    {
        ProArrayAlloc (1, sizeof(ProAnalysisEntity), 1, 
            (ProArray*)&geomitem.shapes);
        
        err = ProCurvedataAlloc (&geomitem.shapes[0].curve);
        TEST_CALL_REPORT ("ProCurvedataAlloc()",
            "ProTestCompCurveResultAction()", err, 
            err != PRO_TK_NO_ERROR);
        err = ProCompositeCurvedataInit (data->components, 
            geomitem.shapes[0].curve);
        TEST_CALL_REPORT ("ProCompositeCurvedataInit()",
            "ProTestCompCurveResultAction()", err, 
            err != PRO_TK_NO_ERROR);

        
    }

    err = ProArrayObjectAdd((ProArray*)geometry, PRO_VALUE_UNUSED, 
        1, &geomitem);
    TEST_CALL_REPORT ("ProArrayObjectAdd()",
        "ProTestCompCurveResultAction()", err, err != PRO_TK_NO_ERROR);

    return(PRO_TK_NO_ERROR);
}