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

#include <ProToolkit.h>
#include <ProElement.h>
#include <ProMfg.h>
#include <ProFeature.h>

typedef struct st_user_data
{
   int dummy;
} UserData;

typedef struct st_user_elem_table
{
    int   elem_type;
    int   value_type;
} UserElemTable;

ProError UserAuxNcseqCreate(
    ProMfg         mfg,          
    ProName        feat_name,   
    int            oper_id,     
    int            retract_id, 
    ProSelection   ncseq_csys,  
    ProName        tool_name,  
    ProFeature    *p_ncseq);

/*================================================================*\
FUNCTION:  UserClcmdCreate()
PURPOSE:   Create a customized, manufacturing CL command.
\*================================================================*/
ProError UserClcmdCreate(
    ProMfg        mfg,           /* manufacturing model */
    int           oper_id,       /* operation identifier */
    int           retract_id,    /* retraction plane identifier */
    ProSelection  ncseq_csys,    /* NC sequence csys */
    ProName       tool_name      /* name of the tool */
)
{
    ProError   status;
    UserData   data;
    ProFeature ncseq;
    ProName    aux_name;

/*----------------------------------------------------------------*\
  Set up the user data required for the CL command creation.
\*----------------------------------------------------------------*/

/*----------------------------------------------------------------*\
  Create the auxiliary NC sequence.
\*----------------------------------------------------------------*/
  status = UserAuxNcseqCreate (mfg, aux_name, oper_id, retract_id,
      ncseq_csys, tool_name, &ncseq);

/*----------------------------------------------------------------*\
  Create the custom NC sequence.
\*----------------------------------------------------------------*/
  if (status == PRO_TK_NO_ERROR)
      status = UserCustomNcseqCreate (mfg, ncseq.id, data);

  return (status);
}

/*================================================================*\
FUNCTION:  UserAuxNcseqCreate()
PURPOSE:   Create an auxiliary NC sequence.
\*================================================================*/
ProError UserAuxNcseqCreate(
    ProMfg         mfg,          /* manufacturing model */
    ProName        feat_name,    /* auxiliary NC sequence name */
    int            oper_id,      /* operation identifier */
    int            retract_id,   /* retraction plane identifier */
    ProSelection   ncseq_csys,   /* NC sequence coordinate system */
    ProName        tool_name,    /* tool name */
    ProFeature    *p_ncseq)      /* auxiliary NC sequence feature */
{
    ProError       status;
    ProErrorlist   errors;       /* error list */
    ProSelection   sel;          /* selection for workpiece */
    ProFeatureCreateOptions *opts = 0;

static UserElemTable elem_tab[] =
    {{PRO_E_FEATURE_TYPE,  PRO_VALUE_TYPE_INT       },
      {PRO_E_FEAT_NAME,    PRO_VALUE_TYPE_WSTRING   },
      {PRO_E_OPERATION,    PRO_VALUE_TYPE_INT       },
      {PRO_E_RETRACT,      PRO_VALUE_TYPE_INT       },
      {PRO_E_CSYS,         PRO_VALUE_TYPE_SELECTION },
      {PRO_E_TOOL,         PRO_VALUE_TYPE_WSTRING   }};

/*----------------------------------------------------------------*\
  Allocate the elements, set the values, and add them to the
  element tree.
\*----------------------------------------------------------------*/

/*----------------------------------------------------------------*\
  Get the ProSelection for the workpiece.
\*----------------------------------------------------------------*/
  if (status == PRO_TK_NO_ERROR)
      status = UserWpieceSelCreate (mfg, PRO_TK_NOT_USED,
          PRO_TK_NOT_USED, &sel);

/*----------------------------------------------------------------*\
  Create the auxiliary NC sequence.
\*----------------------------------------------------------------*/
  if (status == PRO_TK_NO_ERROR)
  	{
      status = ProArrayAlloc(1,sizeof(ProFeatureCreateOptions),
            1, (ProArray*)&opts);

      opts[0]= PRO_FEAT_CR_NO_OPTS;

      status = ProFeatureWithoptionsCreate (sel, elem_tree,
            opts, PRO_REGEN_NO_FLAGS, p_ncseq, &errors);

      status = ProArrayFree((ProArray*)&opts);
     } 
    return (status);
}

/*====================================================================*\
FUNCTION:  UserCustomNcseqCreate()
PURPOSE:   Create a custom NC sequence.
\*====================================================================*/

ProError UserCustomNcseqCreate(
    ProMfg      mfg_model,       /* manufacturing model */
    int         ref_ncseq_id,    /* feature identifier of the
                                    referenced NC sequence */
    UserData   *data)            /* user application data */
{
    ProError      status = PRO_TK_NO_ERROR;
    ProElement    elem, elem_tree;
    ProErrorlist  errors;
    ProSelection  sel;
    ProFeature    custom_feat;
    int           ii;
    ProFeatureCreateOptions *opts = 0;

  static  UserElemTable elem_tab[] = {
     {PRO_E_FEATURE_TYPE,    PRO_VALUE_TYPE_INT   },
     {PRO_E_REF_NCSEQ,       PRO_VALUE_TYPE_INT   },
     {PRO_E_NCL_COMMANDS,    ARRAY                }};

  int elem_type_size = sizeof(elem_tab)/sizeof(UserElemTable);

/*----------------------------------------------------------------*\
  Allocate the feature tree.
\*----------------------------------------------------------------*/
  status = ProElementAlloc (PRO_E_FEATURE_TREE, &elem_tree);

/*----------------------------------------------------------------*\
  Go through the entire element table.
\*----------------------------------------------------------------*/
  for (ii = 0; ii < elem_type_size; ii++)
  {
      status = ProElementAlloc (elem_tab[ii].elem_type, &elem);
      switch (elem_tab[ii].elem_type)
      {
          case PRO_E_FEATURE_TYPE:
               value_data.v.i = PRO_FEAT_BLD_PATH;
               break;
          case PRO_E_REF_NCSEQ:
               value_data.v.i = ref_ncseq_id;
               break;
          case PRO_E_NCL_COMMANDS:
               status = UserClcmdSet (elem, UserCheckClInput, data);
               break;
          default:
               return PRO_TK_GENERAL_ERROR;
               break;
  }

/*----------------------------------------------------------------*\
  Set the value to the element and add it to the element tree.
\*----------------------------------------------------------------*/

}

/*----------------------------------------------------------------*\
  Get the workpiece selection handle.
\*----------------------------------------------------------------*/

/*----------------------------------------------------------------*\
  Create the custom NC sequence.
\*----------------------------------------------------------------*/
  if (status == PRO_TK_NO_ERROR)
  	{
      status = ProArrayAlloc(1,sizeof(ProFeatureCreateOptions),
            1, (ProArray*)&opts);

      opts[0]= PRO_FEAT_CR_NO_OPTS;

      status = ProFeatureWithoptionsCreate (sel, elem_tree,
            opts, PRO_REGEN_NO_FLAGS, &custom_feat, &errors);
      status = ProArrayFree((ProArray*)&opts);      
     }

    return (status);
}

/*================================================================*\
FUNCTION:  UserClcmdSet()
PURPOSE:   Set up the CL command element.
\*================================================================*/

ProError UserClcmdSet(
  ProElement   ncseq_elem,      /* NC sequence element */
  ProFunction  UserCheckFunc,   /* user-supplied check function */
  UserData    *data)            /* user data */
{
    char c     md[80];
    wchar_t    wcmd[80], *wlines[2];
    ProElement cl_cmd_elem;
    double     pos[3], axis[3];
    ProError   status;

/*----------------------------------------------------------------*\
  Set the CL command location and axis.
\*----------------------------------------------------------------*/

/*----------------------------------------------------------------*\
  Prepare the CL command string.
\*----------------------------------------------------------------*/
  ProTKSprintf (cmd, ``MOVETO/ %f,%f,%f'', ...);
  ProStringToWstring  (wcmd, cmd);

/*----------------------------------------------------------------*\
  Check the data.
\*----------------------------------------------------------------*/
  if (UserCheckFunc == NULL || UserCheckFunc (data, pos))
  {
      wlines[0] = wcmd; wlines[1] = NULL;

/*----------------------------------------------------------------*\
  Set up the CL command element and add it to element tree.
\*----------------------------------------------------------------*/
      status = ProClcmdElemCreate (wlines, 1, pos, axis, &cl_cmd_elem);

      if (status == PRO_TK_NO_ERROR)
          status = ProElemtreeElementAdd (ncseq_elem, NULL, cl_cmd_elem);

  }

/*----------------------------------------------------------------*\
  Set notifications, if necessary.
\*----------------------------------------------------------------*/
  if (status == PRO_TK_NO_ERROR)
  {
      ProNotificationSet (PRO_NCL_COMMAND_EXPAND,
          UserClcmdInterpretFunc);

      ProNotificationSet (PRO_NCL_COMMAND_EXPAND,
          UserClcmdLocationGetFunc);
  }

  return (status);

}