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


/*--------------------------------------------------------------------*\
Pro/TOOLKIT includes
\*--------------------------------------------------------------------*/
#include <ProNcseq.h>
#include <ProModelitem.h>
#include <ProMfg.h>
#include <ProSolid.h>
#include <UtilCollect.h>
#include <ProUtil.h>
#include <ProMenu.h>
/*--------------------------------------------------------------------*\
Application includes
\*--------------------------------------------------------------------*/
#include "UtilMfgNew.h"
#include "TestMfgNew.h"
#include "UtilString.h"
#include "UtilGeom.h"
#include "TestError.h"

/*--------------------------------------------------------------------*\
Function prototypes
\*--------------------------------------------------------------------*/
ProNcseq* ProUtilNcseqChoose(ProSolid *p_mfg_solid);
ProError  ProUtilNCseqGetAll(ProSolid *p_mfg_solid, Pro_Test_Ncseq *p_ncseq_array);
ProError  ProTestFeatFilterNcseq(ProModelitem *p_feat, ProAppData tmp_p_nc_seq);
ProError  ProTestNCseqVisit(ProModelitem *p_feat, ProError err, ProAppData tmp_p_nc_seq);
ProNcseq* ProUtilGetNcptr(wchar_t *ncseq_name, Pro_Test_Ncseq *p_nc_seq_array);
ProError  ProUtilToolChoose(ProMfg *p_mfg, ProTool *p_sel_tool);
int       ProUtilToolsGetAll( ProMfg *p_mfg, Pro_Test_Tool *p_all_tools);
ProError  ProTestToolCount( PRO_CONST_ARG ProTool *p_tool, void *num_tool);
ProError  ProTestToolsGet( PRO_CONST_ARG ProTool *p_tool, void *p_tools);
ProError  ProUtilGetToolPtr( wchar_t *tool_id, ProMfg *p_mfg, ProTool *p_tool);


/*====================================================================*\
FUNCTION : ProUtilNcseqChoose()
PURPOSE  : Choose Nc sequence out of all in manufacturing model
\*====================================================================*/
ProNcseq* ProUtilNcseqChoose(ProSolid *p_mfg_solid)
{
    wchar_t title[PRO_NAME_SIZE];
    wchar_t **selected;
    ProNcseq* p_sel_ncseq = NULL;
    ProError status;
    int	n_sel;
    ProFeature *features;
    int features_num, i, made_sel = 0;
    wchar_t **names;
    
    status = ProUtilCollectNCSeqFeat (*p_mfg_solid, &features);
    if (status == PRO_TK_NO_ERROR)
    {
        status = ProArraySizeGet ((ProArray)features, &features_num);
        TEST_CALL_REPORT( "ProArraySizeGet()", "ProUtilNcseqChoose()", 
            status, status != PRO_TK_NO_ERROR );
        names = (wchar_t **)calloc (features_num + 1, sizeof(wchar_t*));
        for (i = 0; i < features_num; i++)
        {
            names[i] = (wchar_t *)calloc (PRO_NAME_SIZE, sizeof(wchar_t));
            status = ProModelitemNameGet(features+i, names[i]);
            TEST_CALL_REPORT("ProModelitemNameGet()",
                "ProUtilNcseqChoose()", status, (status != PRO_TK_NO_ERROR));  
        }
        names[i] = (wchar_t *)calloc (1, sizeof(wchar_t));
        ProStringToWstring (names[i], (char*)"");
        ProStringToWstring(title, (char*)"Select NCsequence");
   	status = ProMenuStringsSelect( title, names,
		1, NULL, &selected, &n_sel );
	if( status == PRO_TK_NO_ERROR && n_sel > 0 )
	{
	    for (i = 0; i < features_num; i++)
	    {
	        if (ProUtilWstrCmp(selected[0], names[i]) == 0)
	        {
	            p_sel_ncseq = (ProNcseq*) calloc(1, sizeof(ProNcseq));
                    p_sel_ncseq->id = features[i].id;
                    p_sel_ncseq->owner = features[i].owner;
                    p_sel_ncseq->type = features[i].type;    
                    made_sel = 1;
	        }
	        free (names[i]);
	    }
	    free (names[i]);
	    free (names);
	}
	if (!made_sel)
	    p_sel_ncseq = NULL;
        status = ProArrayFree ((ProArray*)&features);
        TEST_CALL_REPORT( "ProArrayFree()", "ProUtilNcseqChoose()", 
            status, status != PRO_TK_NO_ERROR );
    }
    return p_sel_ncseq;
}

/*====================================================================*\
FUNCTION : ProTestFeatFilterNcseq()
PURPOSE  : Filter out Nc sequences of the features 
\*====================================================================*/
#if 0
ProError ProTestFeatFilterNcseq(ProModelitem *p_feat, ProAppData tmp_p_nc_seq) 
{
    ProError status;
    ProBoolean is_nc_seq;
    Pro_Test_Ncseq *p_nc_seq = (Pro_Test_Ncseq *) tmp_p_nc_seq;

    status = ProFeatureIsNcseq(p_feat, &is_nc_seq);
    TEST_CALL_REPORT("ProFeatureIsNcseq()",
                        "ProTestFeatFilterNcseq()", status,
                        (status != PRO_TK_NO_ERROR));

    if (is_nc_seq == PRO_B_TRUE)
      (p_nc_seq->num_ncseq)++ ;

    return (is_nc_seq == PRO_B_TRUE? PRO_TK_NO_ERROR : PRO_TK_CONTINUE);

}
#endif

/*====================================================================*\
FUNCTION : ProTestNCseqVisit()
PURPOSE  : Records Nc seq name and pointer into structure ProTestNcseq
\*====================================================================*/
ProError ProTestNCseqVisit(ProModelitem *p_feat, ProError err,
                                              ProAppData tmp_p_nc_seq)
{
    ProError status;
    Pro_Test_Ncseq *p_nc_seq = (Pro_Test_Ncseq *) tmp_p_nc_seq;

    (p_nc_seq->p_ncseq_names)[p_nc_seq->num_ncseq-1] = (wchar_t *) 
                                     calloc(PRO_NAME_SIZE, sizeof(wchar_t));

    status = ProModelitemNameGet(p_feat, 
                (p_nc_seq->p_ncseq_names)[p_nc_seq->num_ncseq-1]);
    TEST_CALL_REPORT("ProModelitemNameGet()",
                        "ProTestNCseqVisit()", status,
                        (status != PRO_TK_NO_ERROR));

    p_nc_seq->p_ncseqptr_array[p_nc_seq->num_ncseq-1] = (ProNcseq*) 
                                                   calloc(1, sizeof(ProNcseq));
   *p_nc_seq->p_ncseqptr_array[p_nc_seq->num_ncseq-1] = * (ProNcseq*)p_feat;

    return PRO_TK_NO_ERROR;
  
}

/*====================================================================*\
FUNCTION : ProUtilGetNcptr()
PURPOSE  : Gets handle to Nc sequence from struct Pro_Test_Ncseq having its name 
\*====================================================================*/
ProNcseq* ProUtilGetNcptr(wchar_t *ncseq_name, Pro_Test_Ncseq *p_nc_seq_array)
{
    ProNcseq* p_ncseq=NULL;
    int i;
    
    for (i=0; i<p_nc_seq_array->num_ncseq; i++)
     {
      if (ProUtilWstrCmp(ncseq_name, p_nc_seq_array->p_ncseq_names[i]) == 0)
        {
         p_ncseq = (ProNcseq*) calloc(1, sizeof(ProNcseq));
         *p_ncseq = *(p_nc_seq_array->p_ncseqptr_array[i]); 
         break;
        }
     }
/*====================================================================*\
      Deallocate structure Pro_Test_Ncseq
\*====================================================================*/
      for (i=0; i<p_nc_seq_array->num_ncseq; i++)
       {
        free (p_nc_seq_array->p_ncseq_names[i]);
        free (p_nc_seq_array->p_ncseqptr_array[i]);
       }
       free (p_nc_seq_array->p_ncseq_names[p_nc_seq_array->num_ncseq]);
       free (p_nc_seq_array->p_ncseq_names);
       free (p_nc_seq_array->p_ncseqptr_array);

   return p_ncseq; 
}

/*====================================================================*\
FUNCTION : ProUtilToolChoose()
PURPOSE  : Let user choose a tool in a mfg model
\*====================================================================*/
ProError ProUtilToolChoose(ProMfg *p_mfg, ProTool *p_sel_tool)
{
     ProError status;
     int num_tools;
     wchar_t **selected;
     Pro_Test_Tool ProTestTool;
     wchar_t title[PRO_NAME_SIZE];
     int	n_sel;

     num_tools =  ProUtilToolsGetAll(p_mfg, &ProTestTool);
     if (num_tools > 0)
        {
          ProStringToWstring(title, (char*)"Select Tools");
	  status = ProMenuStringsSelect( title , ProTestTool.tool_ids, 
		 1, NULL, &selected, &n_sel );
	  if( status == PRO_TK_NO_ERROR && n_sel > 0 )
          {
              status = ProUtilGetToolPtr(selected[0], p_mfg, p_sel_tool);
              return PRO_TK_NO_ERROR;
          }
          else
              return PRO_TK_E_NOT_FOUND;
        }
      else
        return PRO_TK_E_NOT_FOUND;
}


/*====================================================================*\
FUNCTION : ProUtilToolsGetAll()
PURPOSE  : Traverse mfg model for the tools present
\*====================================================================*/
int ProUtilToolsGetAll(
     ProMfg *p_mfg,
     Pro_Test_Tool *p_all_tools)
{
     ProError status;
     int num_tools = 0, i;
     ProTool	    *tools;
     
/*-----------------------------------------------------------*\
 First, count how many tools are in the mfg model
\*-----------------------------------------------------------*/
                        
     status = ProUtilCollectMfgTools (*p_mfg, &tools);
     if (status == PRO_TK_NO_ERROR)
     {
         status = ProArraySizeGet ((ProArray)tools, &num_tools);
         TEST_CALL_REPORT( "ProArraySizeGet()", "ProUtilToolChoose()", 
             status, status != PRO_TK_NO_ERROR );

         status = ProArrayFree ((ProArray*)&tools);
         TEST_CALL_REPORT( "ProArrayFree()", "ProUtilToolChoose()", 
             status, status != PRO_TK_NO_ERROR );
     }

     if (num_tools > 0)
       {
/*-----------------------------------------------------------*\
 Initialize Pro_Test_Tool structure
\*-----------------------------------------------------------*/
         p_all_tools->tool_ids = (wchar_t **)
                          calloc(num_tools + 1, sizeof(wchar_t *));

         p_all_tools->num_tools = 0;

/*----------------------------------------------------------*\
 Get all tools
\*----------------------------------------------------------*/
         status = ProUtilCollectMfgTools (*p_mfg, &tools);
         if (status == PRO_TK_NO_ERROR)
         {
             status = ProArraySizeGet ((ProArray)tools, &num_tools);
             TEST_CALL_REPORT( "ProArraySizeGet()", "ProUtilToolChoose()", 
                 status, status != PRO_TK_NO_ERROR );
             for (i = 0; i < num_tools; i++)
             {
                 status = ProTestToolsGet (tools+i,
 	            (ProAppData)p_all_tools);
             }
             status = ProArrayFree ((ProArray*)&tools);
             TEST_CALL_REPORT( "ProArrayFree()", "ProUtilToolChoose()", 
                 status, status != PRO_TK_NO_ERROR );
         }

         p_all_tools->tool_ids[num_tools] = (wchar_t *)calloc(3, sizeof(wchar_t));
         ProStringToWstring(p_all_tools->tool_ids[num_tools], (char*)"");

      }
  return num_tools;
}


/*====================================================================*\
FUNCTION : ProTestToolCount()
PURPOSE  : action function that counts num of tools
\*====================================================================*/
ProError ProTestToolCount(
        PRO_CONST_ARG ProTool *p_tool,
        void *num_tool)
{
        (* (int *)num_tool)++;
     return PRO_TK_NO_ERROR;
}

/*====================================================================*\
FUNCTION : ProTestToolsGet()
PURPOSE  : action function that fills out Pro_Test_Tool structure
\*====================================================================*/
ProError ProTestToolsGet(
         PRO_CONST_ARG ProTool *p_tool,
         void *p_tools)
{
         Pro_Test_Tool *p_tools_array = (Pro_Test_Tool *)p_tools;
         
         p_tools_array->num_tools ++;

         p_tools_array->tool_ids[p_tools_array->num_tools-1] =
                           (wchar_t *) calloc(PRO_LINE_SIZE, sizeof(wchar_t));
                           
         ProUtilWstrcpy( p_tools_array->tool_ids[p_tools_array->num_tools-1],
                                           (wchar_t *) p_tool->tool_id);

         return PRO_TK_NO_ERROR;
}


/*====================================================================*\
FUNCTION : ProUtilGetToolPtr()
PURPOSE  : Gets handle to a tool from Pro_Test_Tools having its name
\*====================================================================*/
ProError  ProUtilGetToolPtr(
         wchar_t *tool_id,
         ProMfg *p_mfg,
         ProTool *p_tool)
{
             ProUtilWstrcpy(p_tool->tool_id, tool_id);
             p_tool->owner_mfg = *p_mfg;

         return PRO_TK_NO_ERROR;

}