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

#include <ProToolkit.h>
#include <ProMenuBar.h>
#include <ProSurface.h>
#include <ProElement.h>
#include <ProAnnotationFeat.h>
#include <ProAnnotationElem.h>
#include <ProNote.h>

#include <PTAFExamples.h>

/*====================================================================*\
  FUNCTION :	 PTTestAccessNotesSelected()
  PURPOSE  :   Enable access to the button for note/annotation plane conversion
\*====================================================================*/
uiCmdAccessState PTTestAccessNotesSelected(uiCmdAccessMode access_mode)
{
  ProSelection* note_sels;
  int size, i;
  ProModelitem note;

/*---------------------------------------------------------------------*\
Check for one or more selected notes
\*---------------------------------------------------------------------*/
  status = ProSelbufferSelectionsGet (&note_sels);
  PT_TEST_LOG_SUCC ("ProSelbufferSelectionsGet()");

  if (status != PRO_TK_NO_ERROR)
	return ACCESS_UNAVAILABLE;
  
  status = ProArraySizeGet (note_sels, &size);
  PT_TEST_LOG_SUCC ("ProArraySizeGet()");
  
  if (status != PRO_TK_NO_ERROR || size <= 0)
	return ACCESS_UNAVAILABLE;
  
  for (i = 0; i < size; i++)
    {
      status = ProSelectionModelitemGet (note_sels [i], &note);
      PT_TEST_LOG_SUCC ("ProSelectionModelitemGet()");
      
/*---------------------------------------------------------------------*\
If any non-notes are selected, this command can't be used
\*---------------------------------------------------------------------*/
      if (note.type != PRO_NOTE)
	{
	  ProSelectionarrayFree (note_sels);
	  return ACCESS_UNAVAILABLE;
	}
    }
  
  ProSelectionarrayFree (note_sels);
  return ACCESS_AVAILABLE;	  
}

/*====================================================================*\
FUNCTION : PTConvertNoteToAnnotationplane
PURPOSE  : Convert a note to use the selected annotation plane
\*====================================================================*/
ProError PTConvertNoteToAnnotationplane (ProNote* note, ProAnnotationPlane* ap)
{
  ProNoteAttach attach;

/*---------------------------------------------------------------------*\
Extract the current note placement
\*---------------------------------------------------------------------*/
  status = ProNotePlacementGet (note, &attach);
  PT_TEST_LOG_SUCC ("ProNotePlacementGet()");

/*---------------------------------------------------------------------*\
Assign the annotation plane and reassign the placement to the note
\*---------------------------------------------------------------------*/
  status = ProNoteAttachPlaneSet (attach, ap);
  PT_TEST_LOG_SUCC ("ProNoteAttachPlaneSet()");

  status = ProNotePlacementSet (note, attach);
  PT_TEST_LOG_SUCC ("ProNotePlacementSet()");

  status = ProNoteAttachRelease (&attach);
  PT_TEST_LOG_SUCC ("ProNoteAttachRelease()");
  
  return PRO_TK_NO_ERROR;
}

/*====================================================================*\
FUNCTION : PTSelectAnnotationplane
PURPOSE  : Interactively select an datum to be an annotation plane
\*====================================================================*/
ProError PTSelectAnnotationplane (int size, ProAnnotationPlane* ap)
{
  ProSelection* sels = NULL;
  ProGeomitem plane;
  int n_sels;
  ProSurface surf;
  ProGeomitemdata* data;
  ProVector normal;

/*---------------------------------------------------------------------*\
Prompt for the selection
\*---------------------------------------------------------------------*/
  if (size == 1)
    {
      status = ProMessageDisplay (message_file_init,
				  "PTNC Select the datum plane to use as the annotation plane for the note.");
      PT_TEST_LOG_SUCC ("ProMessageDisplay()");
    }
  else
    {
      status = ProMessageDisplay (message_file_init,
				  "PTNC Select the datum plane to use as the annotation plane for the notes.");
      PT_TEST_LOG_SUCC ("ProMessageDisplay()");
    }

  status = ProSelect ("datum", 1, NULL, NULL, NULL, NULL, &sels, &n_sels);
  PT_TEST_LOG_SUCC ("ProSelect()");
  
  if (status != PRO_TK_NO_ERROR)
    return status;

  status = ProSelectionUnhighlight (sels [0]);
  PT_TEST_LOG_SUCC ("ProSelectionUnhighlight()");

/*---------------------------------------------------------------------*\
Extract the selected datum plane as a surface
\*---------------------------------------------------------------------*/
  status = ProSelectionModelitemGet (sels [0], &plane);
  PT_TEST_LOG_SUCC ("ProSelectionModelitemGet()");

  status = ProGeomitemToSurface (&plane, &surf);
  PT_TEST_LOG_SUCC ("ProGeomitemToSurface()");

/*---------------------------------------------------------------------*\
Extract the surface data to get the surface normal vector
\*---------------------------------------------------------------------*/
  status = ProSurfaceDataGet (surf, &data); 
  PT_TEST_LOG_SUCC ("ProSurfaceDataGet()");

  memcpy (normal, data->data.p_surface_data->srf_shape.plane.e3, sizeof (ProVector));

  status = ProGeomitemdataFree (&data);
  PT_TEST_LOG_SUCC ("ProGeomitemdataFree()");

/*---------------------------------------------------------------------*\
Create the annotation plane
\*---------------------------------------------------------------------*/
  status = ProAnnotationplaneCreate (sels[0], normal, ap);
  PT_TEST_LOG_SUCC ("ProAnnotationplaneCreate()");

  if (status != PRO_TK_NO_ERROR)
	return status;

  return PRO_TK_NO_ERROR;
}

/*====================================================================*\
FUNCTION : PTNoteConvert
PURPOSE  : Convert one or more selected notes to use annotation planes
\*====================================================================*/
int PTNoteConvert ()
{
  ProSelection* note_sels  = NULL;
  int size, i;
  ProNote note;
  ProAnnotationPlane ap;
  
  ap.id = PRO_VALUE_UNUSED;

/*---------------------------------------------------------------------*\
Extract the selected notes
\*---------------------------------------------------------------------*/
  status = ProSelbufferSelectionsGet (&note_sels);
  PT_TEST_LOG_SUCC ("ProSelbufferSelectionsGet()");

  status = ProArraySizeGet (note_sels, &size);
  PT_TEST_LOG_SUCC ("ProArraySizeGet()");

  for (i = 0; i < size; i++)
    {
      status = ProSelectionModelitemGet (note_sels [i], &note);
      PT_TEST_LOG_SUCC ("ProSelectionModelitemGet()");
      
      if (note.type == PRO_NOTE)
	{
/*---------------------------------------------------------------------*\
If the user has not yet selected the annotation plane, prompt for this
\*---------------------------------------------------------------------*/
	  if (ap.id == PRO_VALUE_UNUSED)
	    {
	      status = PTSelectAnnotationplane (size, &ap);
	      if (status != PRO_TK_NO_ERROR)
		return status;
	    }

/*---------------------------------------------------------------------*\
Hide the note, add the annotation plane, and redisplay the note
\*---------------------------------------------------------------------*/      
	  status = ProAnnotationUndisplay (&note, NULL, NULL);
	  PT_TEST_LOG_SUCC ("ProAnnotationUndisplay()");
	  
	  PTConvertNoteToAnnotationplane (&note, &ap);
	  
	  status = ProAnnotationDisplay (&note, NULL, NULL, NULL);
	  PT_TEST_LOG_SUCC ("ProAnnotationDisplay()");
	} 
    }

  status = ProSelbufferClear ();
  PT_TEST_LOG_SUCC ("ProSelbufferClear()");
 
/*---------------------------------------------------------------------*\
Reselect the notes for the next operation
\*---------------------------------------------------------------------*/ 
  for (i = 0; i < size; i++)
    {
      status = ProSelbufferSelectionAdd  (note_sels[i]);
      PT_TEST_LOG_SUCC ("ProSelbufferSelectionAdd()");
    }
  
  ProSelectionarrayFree (note_sels);

  return (1);
}