package org.sparx.javaexample.examples;

import java.io.File;

import javax.swing.DefaultListModel;
import javax.swing.JOptionPane;

import org.sparx.Collection;
import org.sparx.Element;
import org.sparx.Method;
import org.sparx.MethodConstraint;
import org.sparx.MethodTag;
import org.sparx.Parameter;
import org.sparx.Repository;
import org.sparx.javaexample.ExampleHelpers;
import org.sparx.javaexample.ExampleUI;


public class MethodLifecycleExample implements IExample
{
	/*
	 * (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString()
	{
		return "Method Lifecycle";
	}
	
	/*
	 * (non-Javadoc)
	 * @see org.sparx.javaexample.test.IExample#getDescription()
	 */
	public String getDescription()
	{
		return "An example of working with methods.<br/><br/><b>NOTE:</b> Requires an element id to work on, so try running <code>Dump Model Diagrams</code> or <code>Dump Model</code> first and note a suitable element ID down.<br/><br/><b>Related APIs</b><br/><ul><li><a href='http://www.sparxsystems.com.au/EAUserGuide/index.html?method.htm'>Method API</a></li></ul>";
	}

	/*
	 * (non-Javadoc)
	 * @see org.sparx.javaexample.test.IExample#runExample(java.io.File, javax.swing.DefaultListModel)
	 */
	public void runExample( File projectFile, ExampleUI uiFrame )
	{
		Repository rep = null;
		DefaultListModel outputList = uiFrame.getOutputListModel();
		
		// Prompt the user for an Element ID to work on
		short elementID = ExampleHelpers.promptForShortID( 
				"Enter an Element ID to work on", uiFrame);
		
		if ( elementID < 0 )
		{
			outputList.addElement( "Method Lifecycle Example cancelled by user" );
			return;
		}
		
		try
		{
			// Create a repository object - This will create a new instance of EA
			rep = new Repository();
			
			// Attempt to open the provided file
			if ( rep.OpenFile(projectFile.getAbsolutePath()) )
			{
				Element theElement = rep.GetElementByID( elementID );
				
				// ==================================================
				// ADD AN ELEMENT
				// ==================================================
				Collection<Method> methods = theElement.GetMethods();
				Method newMethod = methods.AddNew( "DoSomething", "bool" );
				newMethod.Update();				
				methods.Refresh();
				
				int addedMethodID = newMethod.GetMethodID();
				
				outputList.addElement( "Added method: " + newMethod.GetName() 
						+ "(ID=" + addedMethodID + ")" );
				
				// ==================================================
				// MANAGE METHOD PRECONDITIONS
				// ==================================================
				// Add a precondition
				Collection<MethodConstraint> preConditions = newMethod.GetPreConditions();
				String preConditionName = "TestPreCondition";
				MethodConstraint newPreCondition
						= preConditions.AddNew( preConditionName, "Precision" );
				newPreCondition.Update();
				preConditions.Refresh();
				
				outputList.addElement( "Added Precondition: " + newPreCondition.GetName() );
				
				newPreCondition = null;
								
				// Search the collection for the added precondition and delete it
				for ( short i = 0 ; i < preConditions.GetCount() ; i++ )
				{
					MethodConstraint currentPreCondition = preConditions.GetAt( i );
					String currentPreConditionName = currentPreCondition.GetName();
					outputList.addElement( "Pre Condition: " + currentPreConditionName );
					
					// Delete the precondition we just added
					if ( currentPreConditionName.equals(preConditionName) )
					{
						preConditions.DeleteAt( i, false );
						outputList.addElement( "Deleted PreCondition: " + currentPreConditionName);
					}
				}
				
				preConditions = null;
				
				// ==================================================
				// MANAGE METHOD POSTCONDITIONS
				// ==================================================
				// Add a postcondition
				Collection<MethodConstraint> postConditions = newMethod.GetPostConditions();
				String postConditionName = "TestPostCondition";
				MethodConstraint newPostCondition
						= postConditions.AddNew( postConditionName, "Precision" );
				newPostCondition.Update();
				postConditions.Refresh();
				
				outputList.addElement( "Added Postcondition: " + newPostCondition.GetName() );
				
				newPreCondition = null;
								
				// Search the collection for the added postcondition and delete it
				for ( short i = 0 ; i < postConditions.GetCount() ; i++ )
				{
					MethodConstraint currentPostCondition = postConditions.GetAt( i );
					String currentPostConditionName = currentPostCondition.GetName();
					outputList.addElement( "Post Condition: " + currentPostConditionName );
					
					// Delete the postcondition we just added
					if ( currentPostConditionName.equals(postConditionName) )
					{
						postConditions.DeleteAt( i, false );
						outputList.addElement( "Deleted PostCondition: " + currentPostConditionName);
					}
				}
				
				postConditions = null;
				
				// ==================================================
				// MANAGE METHOD TAGGED VALUES
				// ==================================================
				// Add an attribute tag
				Collection<MethodTag> tags = newMethod.GetTaggedValues();
				String tagName = "MyMethodTag";
				MethodTag newTag 
						= tags.AddNew( tagName, "Number" );
				newTag.Update();
				tags.Refresh();
				
				outputList.addElement( "Added tag: " + newTag.GetName() 
						+ " (ID=" + newTag.GetTagID() + ")" );
				int newTagID = newTag.GetTagID();
				
				newTag = null;
				
				
				// Search the tag collection for the added tag and delete it
				for ( short i = 0 ; i < tags.GetCount() ; i++ )
				{
					MethodTag currentTag = tags.GetAt( i );
					int currentTagID = currentTag.GetTagID();
					String currentTagName = currentTag.GetName();
					outputList.addElement( "Method Tag: " + currentTagName );
										
					// Delete the tag we just added
					if ( currentTagID == newTagID )
					{
						tags.DeleteAt( i, false );
						outputList.addElement( "Deleted Tag: " + currentTagName
								+ " (ID=" + currentTag.GetTagID() + ")");
					}
				}
				
				tags = null;
				
				// ==================================================
				// MANAGE METHOD PARAMETERS
				// ==================================================
				// Add a method parameter
				Collection<Parameter> parameters = newMethod.GetParameters();
				String parameterName = "sName";
				Parameter newParameter
						= parameters.AddNew( parameterName, "String" );
				newParameter.Update();
				parameters.Refresh();
				
				outputList.addElement( "Added parameter: " + newParameter.GetName() );
				
				newParameter = null;
								
				// Search the parameter collection for the added parameter and delete it
				for ( short i = 0 ; i < parameters.GetCount() ; i++ )
				{
					Parameter currentParameter = parameters.GetAt( i );
					String currentParameterName = currentParameter.GetName();
					outputList.addElement( "Method Parameter: " + currentParameterName );
					
					// Delete the parameter we just added
					if ( currentParameterName.equals(parameterName) )
					{
						parameters.DeleteAt( i, false );
						outputList.addElement( "Deleted Parameter: " + currentParameterName);
					}
				}
				
				parameters = null;
				
				// ==================================================
				// LIST AND DELETE METHODS
				// ==================================================
				newMethod = null;
				
				// List methods
				for ( short i = 0 ; i < methods.GetCount() ; i++ )
				{
					Method currentMethod = methods.GetAt( i );
					int currentMethodID = currentMethod.GetMethodID();
					String currentMethodName = currentMethod.GetName();
					
					outputList.addElement( "Method: " + currentMethodName );
					
					// Delete the attribute we added
					if ( currentMethodID == addedMethodID )
					{
						methods.DeleteAt( i, false );
						outputList.addElement( "Deleted Method: " + currentMethodName 
								+ "(ID=" + currentMethodID + ")" );					
					}					
				}
				
				outputList.addElement( "Done!" );
			}
			else
			{
				// If the file couldn't be opened then notify the user
				String message = "EA was unable to open the file '";
				message += projectFile.getAbsolutePath();
				message += "'.";
				JOptionPane.showMessageDialog( uiFrame, message, "Invalid File", JOptionPane.ERROR_MESSAGE );
				outputList.addElement( message );
			}
		}
		catch ( UnsatisfiedLinkError ule )
		{
			String message = "Unable to communicate with EA.\nPlease ensure that the path to SSJavaCOM.dll included in java.library.path";
			JOptionPane.showMessageDialog( uiFrame, message, "Unable to link to SSJavaCOM.dll", JOptionPane.ERROR_MESSAGE );
			outputList.addElement( message );
		}
		catch ( Exception e )
		{
			String message = "An unhandled exception was thrown: " + e.getMessage();
			JOptionPane.showMessageDialog( uiFrame, message, "Unhandled Exception", JOptionPane.ERROR_MESSAGE );
			outputList.addElement( message );
		}
		finally
		{
			if ( rep != null )
			{
				// Clean up
				rep.CloseFile();
				rep.Exit();
				rep.destroy();
			}
		}
	}

}
