package org.sparx.javaexample.examples;

import java.io.File;

import javax.swing.DefaultListModel;
import javax.swing.JOptionPane;

import org.sparx.Attribute;
import org.sparx.AttributeConstraint;
import org.sparx.AttributeTag;
import org.sparx.Collection;
import org.sparx.Element;
import org.sparx.Repository;
import org.sparx.javaexample.ExampleHelpers;
import org.sparx.javaexample.ExampleUI;


public class AttributeLifecycleExample implements IExample
{	
	/*
	 * (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString()
	{
		return "Attribute Lifecycle";
	}
	
	/*
	 * (non-Javadoc)
	 * @see org.sparx.javaexample.test.IExample#getDescription()
	 */
	public String getDescription()
	{
		return "An example of working with attributes.<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?attribute.htm'>Attribute 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( "Attribute 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()) )
			{
				// Get the element to work on
				Element theElement = rep.GetElementByID( elementID );
				outputList.addElement( "Working on element '" + theElement.GetName() 
						+ "' (Type=" + theElement.GetType() + " ID=" 
						+ theElement.GetElementID() + ")" );
				
				// ==================================================
				// ADD AN ATTRIBUTE
				// ==================================================
				// Create an attribute to work on
				Collection<Attribute> attributes = theElement.GetAttributes();
				Attribute newAttribute = attributes.AddNew( "m_number", "int" );
				newAttribute.Update();				
				attributes.Refresh();
				
				outputList.addElement( "Added attribute: " + newAttribute.GetName() 
						+ "(Type=" + newAttribute.GetType() + ", ID=" 
						+ newAttribute.GetAttributeID() + ")" );
				
				int addedAttributeID = newAttribute.GetAttributeID();
				
				// ==================================================
				// MANAGE ATTRIBUTE CONSTRAINTS
				// ==================================================
				// Add an attribute constraint
				Collection<AttributeConstraint> constraints = newAttribute.GetConstraints();
				String constraintName = "> 123";
				AttributeConstraint newConstraint 
						= constraints.AddNew( constraintName, "Precision" );
				newConstraint.Update();
				constraints.Refresh();
				
				outputList.addElement( "Added constraint: " + newConstraint.GetName() );
				
				newConstraint = null;
								
				// Search the constraint collection for the added constraint and delete it
				for ( short i = 0 ; i < constraints.GetCount() ; i++ )
				{
					AttributeConstraint currentConstraint = constraints.GetAt( i );
					String currentConstraintName = currentConstraint.GetName();
					outputList.addElement( "Attribute Constraint: " + currentConstraintName );
					
					// Delete the constraint we just added
					if ( currentConstraintName.equals(constraintName) )
					{
						constraints.DeleteAt( i, false );
						outputList.addElement( "Deleted Constraint: " + currentConstraintName);
					}
				}
				
				constraints = null;
				
				// ==================================================
				// MANAGE ATTRIBUTE TAGGED VALUES
				// ==================================================
				// Add an attribute tag
				Collection<AttributeTag> tags = newAttribute.GetTaggedValues();
				String tagName = "MyAttributeTag";
				AttributeTag 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++ )
				{
					AttributeTag currentTag = tags.GetAt( i );
					int currentTagID = currentTag.GetTagID();
					String currentTagName = currentTag.GetName();
					outputList.addElement( "Attribute 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;
								
				// ==================================================
				// LIST AND DELETE ATTRIBUTES
				// ==================================================
				newAttribute = null;
				
				// List attributes
				for ( short i = 0 ; i < attributes.GetCount() ; i++ )
				{
					Attribute currentAttribute = attributes.GetAt( i );
					int currentAttributeID = currentAttribute.GetAttributeID();
					String currentAttributeName = currentAttribute.GetName();
					
					outputList.addElement( "Attribute: " + currentAttributeName );
					
					// Delete the attribute we added
					if ( currentAttributeID == addedAttributeID )
					{
						attributes.DeleteAt( i, false );
						outputList.addElement( "Deleted Attribute: " + currentAttributeName 
								+ "(Type=" + currentAttribute.GetType() 
								+ ", ID=" + currentAttributeID + ")" );					
					}					
				}
				
				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();
			}
		}
	}	
}
