package org.sparx.javaexample.examples;

import java.io.File;

import javax.swing.DefaultListModel;
import javax.swing.JOptionPane;

import org.sparx.Collection;
import org.sparx.Constraint;
import org.sparx.Effort;
import org.sparx.Element;
import org.sparx.Issue;
import org.sparx.Metric;
import org.sparx.Repository;
import org.sparx.Risk;
import org.sparx.Scenario;
import org.sparx.TaggedValue;
import org.sparx.Test;
import org.sparx.javaexample.ExampleHelpers;
import org.sparx.javaexample.ExampleUI;


public class ElementExtrasExample implements IExample
{
	/*
	 * (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString()
	{
		return "Element Extras";
	}
	
	/*
	 * (non-Javadoc)
	 * @see org.sparx.javaexample.test.IExample#getDescription()
	 */
	public String getDescription()
	{
		return "Examples of how to access and use element extras - such as scenarios, constraints and requirements.<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?element2.htm'>Element 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( "Element Extras 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() + ")" );
								
				// ==================================================
				// MANAGE ELEMENT CONSTRAINTS
				// ==================================================
				outputList.addElement( "Constraints" );
				
				// Add a new constraint
				Collection<Constraint> constraints = theElement.GetConstraints();
				String newConstraintName = "MyConstraint";
				Constraint newConstraint = constraints.AddNew( newConstraintName, "Pre-condition" );
				newConstraint.Update();
				constraints.Refresh();
				
				outputList.addElement( "    Added new Constraint: " + newConstraint.GetName() );				
				newConstraint = null;
				
				// List all element constraints
				for ( short i = 0 ; i < constraints.GetCount() ; i++ )
				{
					Constraint currentConstraint = constraints.GetAt( i );
					String currentConstraintName = currentConstraint.GetName();
					
					outputList.addElement( "    Constraint: " + currentConstraintName );
					
					// Delete the constraint that we just added
					if ( currentConstraintName.equals(newConstraintName) )
					{
						constraints.DeleteAt( i, false );
						outputList.addElement( "    Deleted Constraint: " + currentConstraintName );
					}	
				}
				
				constraints = null;
				
				// ==================================================
				// MANAGE ELEMENT EFFORTS
				// ==================================================
				outputList.addElement( "Efforts" );
				
				// Add a new effort
				Collection<Effort> efforts = theElement.GetEfforts();
				String newEffortName = "MyEffort";
				Effort newEffort = efforts.AddNew( newEffortName, "Coding" );
				newEffort.Update();
				efforts.Refresh();
				
				outputList.addElement( "    Added new Effort: " + newEffort.GetName() );				
				newEffort = null;
				
				// List all efforts
				for ( short i = 0 ; i < efforts.GetCount() ; i++ )
				{
					Effort currentEffort = efforts.GetAt( i );
					String currentEffortName = currentEffort.GetName();
					
					outputList.addElement( "    Effort: " + currentEffortName );
					
					// Delete the effort that we just added
					if ( currentEffortName.equals(newEffortName) )
					{
						efforts.DeleteAt( i, false );
						outputList.addElement( "    Deleted Effort: " + currentEffortName );
					}	
				}
				
				efforts = null;
				
				// ==================================================
				// MANAGE ELEMENT RISKS
				// ==================================================
				outputList.addElement( "Risks" );
				
				
				// Add a new risk
				Collection<Risk> risks = theElement.GetRisks();
				String newRiskName = "MyRisk";
				Risk newRisk = risks.AddNew( newRiskName, "Time" );
				newRisk.Update();
				risks.Refresh();
				
				outputList.addElement( "    Added new Risk: " + newRisk.GetName() );				
				newRisk = null;
				
				// List all element risks
				for ( short i = 0 ; i < risks.GetCount() ; i++ )
				{
					Risk currentRisk = risks.GetAt( i );
					String currentRiskName = currentRisk.GetName();
					
					outputList.addElement( "    Risk: " + currentRiskName );
					
					// Delete the risk that we just added
					if ( currentRiskName.equals(newRiskName) )
					{
						risks.DeleteAt( i, false );
						outputList.addElement( "    Deleted Risk: " + currentRiskName );
					}	
				}
				
				risks = null;
				
				// ==================================================
				// MANAGE ELEMENT METRICS
				// ==================================================
				outputList.addElement( "Metrics" );
				
				// Add a new issue
				Collection<Metric> metrics = theElement.GetMetrics();
				String newMetricName = "MyMetric";
				Metric newMetric = metrics.AddNew( newMetricName, "Cost" );
				newMetric.Update();
				metrics.Refresh();
				
				outputList.addElement( "    Added new Metric: " + newMetric.GetName() );				
				newMetric = null;
				
				// List all metrics
				for ( short i = 0 ; i < metrics.GetCount() ; i++ )
				{
					Metric currentMetric = metrics.GetAt( i );
					String currentMetricName = currentMetric.GetName();
					
					outputList.addElement( "    Metric: " + currentMetricName );
					
					// Delete the metric that we just added
					if ( currentMetricName.equals(newMetricName) )
					{
						metrics.DeleteAt( i, false );
						outputList.addElement( "    Deleted Metric: " + currentMetricName );
					}	
				}
				
				metrics = null;				
				
				// ==================================================
				// MANAGE ELEMENT TAGGED VALUES
				// ==================================================
				outputList.addElement( "Tagged Values" );
				
				// Add a new tag
				Collection<TaggedValue> tags = theElement.GetTaggedValues();
				String newTagName = "MyTag";
				TaggedValue newTag = tags.AddNew( newTagName, "Number" );
				newTag.Update();
				tags.Refresh();
				
				outputList.addElement( "    Added new Tag: " + newTag.GetName() );				
				newTag = null;
				
				// List all element tags
				for ( short i = 0 ; i < tags.GetCount() ; i++ )
				{
					TaggedValue currentTag = tags.GetAt( i );
					String currentTagName = currentTag.GetName();
					
					outputList.addElement( "    Tagged Value: " + currentTagName );
					
					// Delete the tag that we just added
					if ( currentTagName.equals(newTagName) )
					{
						tags.DeleteAt( i, false );
						outputList.addElement( "    Deleted Tag: " + currentTagName );
					}	
				}
				
				tags = null;

				// ==================================================
				// MANAGE ELEMENT SCENARIOS
				// ==================================================
				outputList.addElement( "Scenarios" );
				
				// Add a new scenario
				Collection<Scenario> scenarios = theElement.GetScenarios();
				String newScenarioName = "MyScenario";
				Scenario newScenario = scenarios.AddNew( newScenarioName, "Alternate" );
				newScenario.Update();
				scenarios.Refresh();
				
				outputList.addElement( "    Added new Scenario: " + newScenario.GetName() );				
				newScenario = null;
				
				// List all element scenarios
				for ( short i = 0 ; i < scenarios.GetCount() ; i++ )
				{
					Scenario currentScenario = scenarios.GetAt( i );
					String currentScenarioName = currentScenario.GetName();
					
					outputList.addElement( "    Scenario: " + currentScenarioName );
					
					// Delete the Scenario that we just added
					if ( currentScenarioName.equals(newScenarioName) )
					{
						scenarios.DeleteAt( i, false );
						outputList.addElement( "    Deleted Scenario: " + currentScenarioName );
					}	
				}
				
				scenarios = null;				
				
				// ==================================================
				// MANAGE ELEMENT FILES
				// ==================================================
				outputList.addElement( "Files" );
				
				// Add a new issue
				Collection<org.sparx.File> files = theElement.GetFiles();
				String newFileName = "MyFile";
				org.sparx.File newFile = files.AddNew( newFileName, "doc" );
				newFile.Update();
				files.Refresh();
				
				outputList.addElement( "    Added new File: " + newFile.GetName() );				
				newFile = null;
				
				// List all element files
				for ( short i = 0 ; i < files.GetCount() ; i++ )
				{
					org.sparx.File currentFile = files.GetAt( i );
					String currentFileName = currentFile.GetName();
					
					outputList.addElement( "    File: " + currentFileName );
					
					// Delete the file that we just added
					if ( currentFileName.equals(newFileName) )
					{
						files.DeleteAt( i, false );
						outputList.addElement( "    Deleted File: " + currentFileName );
					}	
				}
				
				files = null;
				
				// ==================================================
				// MANAGE ELEMENT ISSUES
				// ==================================================
				outputList.addElement( "Tests" );
				
				// Add a new test
				Collection<Test> tests = theElement.GetTests();
				String newTestName = "MyTest";
				Test newTest = tests.AddNew( newTestName, "Unit" );
				newTest.Update();
				tests.Refresh();
				
				outputList.addElement( "    Added new Test: " + newTest.GetName() );				
				newTest = null;
				
				// List all element Tests
				for ( short i = 0 ; i < tests.GetCount() ; i++ )
				{
					Test currentTest = tests.GetAt( i );
					String currentTestName = currentTest.GetName();
					
					outputList.addElement( "    Test: " + currentTestName );
					
					// Delete the Test that we just added
					if ( currentTestName.equals(newTestName) )
					{
						tests.DeleteAt( i, false );
						outputList.addElement( "    Deleted Test: " + currentTestName );
					}	
				}
				
				tests = null;
				
				// ==================================================
				// MANAGE ELEMENT ISSUES
				// ==================================================
				outputList.addElement( "Issues" );
				
				// Add a new issue
				Collection<Issue> issues = theElement.GetIssues();
				String newIssueName = "MyIssue";
				Issue newIssue = issues.AddNew( newIssueName, "Defect" );
				newIssue.Update();
				issues.Refresh();
				
				outputList.addElement( "    Added new Issue: " + newIssue.GetName() );				
				newIssue = null;
				
				// List all element issues
				for ( short i = 0 ; i < issues.GetCount() ; i++ )
				{
					Issue currentIssue = issues.GetAt( i );
					String currentIssueName = currentIssue.GetName();
					
					outputList.addElement( "    Issue: " + currentIssueName );
					
					// Delete the issue that we just added
					if ( currentIssueName.equals(newIssueName) )
					{
						issues.DeleteAt( i, false );
						outputList.addElement( "    Deleted Issue: " + currentIssueName );
					}	
				}
				
				issues = null;
				
				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();
			}
		}
	}

}
