/* Handles startup.
*/
static AIErr StartupPlugin ( SPInterfaceMessage* message )
{
	AIErr error = kNoErr;
	error = AcquireSuites( message->d.basic );
	if (!error) {
		// Allocate our globals - Illustrator will keep track of these.
		error = message->d.basic->AllocateBlock( sizeof(Globals), (void **) &g );
		if ( !error ) { 
			message->d.globals = g;
		}
	}
	if (!error) {
		error = AddMenu(message);
	}
	if (!error) {	
		error = AddFilter(message);
	}
	if (!error) {
		error = AddTool(message);
	}
	if (!error) {
		error = AddAction(message);
	}
	ReleaseSuites( message->d.basic );
	return error;
}
/* Handles mouse down event for this plug-in's tool.
*/
static AIErr ToolMouseDown( AIToolMessage* message ) 
{

	AIErr 	error = kNoErr;
	AIArtHandle path;
	AIPathSegment segment;	
	long 	count = 0;
	AIMatchingArtSpec spec[1];
	AIArtHandle **matches;
	short segmentCount = 0;

	error = AcquireSuites( ((SPInterfaceMessage*)message)->d.basic );

	// Get the current selection (if any).
	if ( !error ) {
		spec[0].type = kPathArt;
		spec[0].whichAttr = kArtSelected;
		spec[0].attr = kArtSelected;
		error = sAIMatchingArt->GetMatchingArt( spec, 1, &matches, &count );
	}

	bool addPoint = false;
	if ( !error ) {
		if ( count == 0 ) {
			addPoint = true;
			// There is no selection, so make a new path.
			error = sAIArt->NewArt( kPathArt, kPlaceAboveAll, nil, &path );
			
			// Select it so we find it later.
			if (!error) {
				error = sAIArt->SetArtUserAttr( path, kArtSelected, kArtSelected );
			}
		}
		else if ( count == 1 ) {
			addPoint = true;
			path = (*matches)[0];
		}
	}

	//  Add point to the path at the mouse down location.
	if ( !error && addPoint) {
		error = sAIPath->GetPathSegmentCount( path, &segmentCount );
		// All of the segments are corners
		if ( !error) {
			segment.corner = true;  
			segment.p.h = message->cursor.h;
			segment.p.v = message->cursor.v;
			segment.in = segment.out = segment.p;
			error = sAIPath->SetPathSegments( path, segmentCount, 1, &segment );
		}
	}

	ReleaseSuites( message->d.basic );
	return error;
}
/* Applies this plug-in's filter.
*/
static AIErr GoFilter( AIFilterMessage* message )
{
	AIErr 	error = kNoErr;
	MyFilterParameters** parms_handle = (MyFilterParameters **) message->parameters;

	error = AcquireSuites( ((SPInterfaceMessage*)message)->d.basic );

	// Do your stuff here, for example...

	// Create a new path.
	AIArtHandle path;
	if ( !error ) {
		error = sAIArt->NewArt( kPathArt, kPlaceAboveAll, nil, &path );
	}

	// Find the point on the page that's in the middle of the window.
	AIRealPoint center;
	if ( !error ) {
		error = sAIDocumentView->GetDocumentViewCenter( nil, &center );
	}

	// Create the polygon points, randomly located around the center.
	if ( !error ) {
		ASInt32  corners = (**parms_handle).corners;
		ASInt32  size = (**parms_handle).size;
		AIPathSegment segment;
		// All of the segments are corners
		segment.corner = true;
		for (short i = 0; i < corners; ++i ) {
			segment.p.h = center.h +
						  sAIMath->AIRealMul( sAIRandom->FloatRnd() - kAIRealHalf, (AIReal) size );
			segment.p.v = center.v +
						  sAIMath->AIRealMul( sAIRandom->FloatRnd() - kAIRealHalf, (AIReal) size );
			segment.in = segment.out = segment.p;
			error = sAIPath->SetPathSegments( path, i, 1, &segment );
			if ( error ) 
				break;
		}
	}

	// Close the path.
	if ( !error ) {
		error = sAIPath->SetPathClosed( path, true );
	}

	// Allow the filter to be recorded as an action event.
	if ( !error ) {
		error = RecordFilterAction(**parms_handle);
	}
	
	ReleaseSuites( message->d.basic );
	return error;
}
/* Handles this plug-in's menus.
*/
static AIErr GoMenu ( AIMenuMessage* message )
{
	AIErr error = kNoErr;
	error = AcquireSuites( message->d.basic );
	if (!error) {
		if (message->menuItem == g->aboutPluginMenu) {
			// Pop this plug-ins about box.
			SDKAboutPluginsHelper aboutPluginsHelper;
			aboutPluginsHelper.PopAboutBox(message, "About Tutorial", kSDKDefAboutSDKCompanyPluginsAlertString);
		}
	}
	ReleaseSuites( message->d.basic );
	return error;
}
/* Prompts for input parameters for this plug-in's filter.
*/
static AIErr GetFilterParameters( AIFilterMessage* message ) 
{
	AIErr error = kNoErr;
	MyFilterParameters** parms_handle;

	error = AcquireSuites( ((SPInterfaceMessage*)message)->d.basic );

	// Create buffer for filter parameters if we are not given a buffer to use.
	if (!error) {
		parms_handle = (MyFilterParameters **) message->parameters;
		if ( !parms_handle ) {
			error = sAIMDMemory->MdMemoryNewHandle( sizeof( MyFilterParameters ), ( AIMdMemoryHandle *)&message->parameters);
			if ( !error && !message->parameters) {
					error = kOutOfMemoryErr;
			}
			if (!error) {
				// Set default parameter values.
				parms_handle = ( MyFilterParameters **) message->parameters;
				**parms_handle = kDefaultFilterParameters;
			}
		}
	}

	// Pop a dialog to allow the user to tune the filter's parameters.
	if (!error) {
		// See InitializeFilterDialog() for the dialog initialization procedure.
		// See HandleFilterDialogOKButton() for the dialog dismissal procedure.
		MyFilterParameters orig_params = **parms_handle;
		AIErr result = sADMDialog->Modal(message->d.self, "Tutorial Dialog", kTutorialDLOG, 
			kADMModalDialogStyle, InitializeFilterDialog, (ADMUserData)parms_handle, 0);
		bool cancelled = kDlgOKButton == result ? false : true; 
		
		// If the cancel button was hit, restore original parameters.
		if (cancelled)
		{
			**parms_handle = orig_params;
			error = kCanceledErr;
		}
	}

	ReleaseSuites( message->d.basic );
	return error;
}
/* Executes this plug-in's action. 
 * This routine gets called when your plug-in gets called with kActionCaller/kDoActionSelector
 * Your plug-in is being run by the Actions panel.
*/
static AIErr DoAction(DoActionMessage* doActionMessage)
{
	ASErr error = kNoErr;
	MyFilterParameters** params_handle;
	AIFilterMessage filterMessageStruct, *filterMessage;
	
	error = AcquireSuites( doActionMessage->d.basic );

	// Allocate instance of struct MyFilterParameters
	if (!error) {
		filterMessage = &filterMessageStruct;
		filterMessage->d = doActionMessage->d;
		error = sAIMDMemory->MdMemoryNewHandle( sizeof( MyFilterParameters ), ( AIMdMemoryHandle *)&filterMessage->parameters);
		if ( !error && !filterMessage->parameters ) {
			error = kOutOfMemoryErr;
		}
	}

	// Extract parameter values from the the Value Parameter Block (VPB). 
	if (!error) {
		AIActionParamValueRef valueParameterBlock = doActionMessage->param;
		params_handle = ( MyFilterParameters **) filterMessage->parameters;
		error = sAIActionManager->AIActionGetInteger(valueParameterBlock, 'crnr', &(*params_handle)->corners);
		if (!error) {
			error = sAIActionManager->AIActionGetInteger(valueParameterBlock, 'size', &(*params_handle)->size);
		}
	}

	// Pop filter parameters dialog if asked to.
	if (!error && doActionMessage->showDialog) {
		error = GetFilterParameters( filterMessage );
	} 

	// Apply the filter.
	if (!error) {
		error = GoFilter( filterMessage );
	}

	ReleaseSuites( doActionMessage->d.basic );
	return error;
}
Suites::~Suites()
{
	ReleaseSuites();
}