/* Copyright ? 2005 Adobe Systems Incorporated and its suppliers. All rights reserved.
 * 
 * This file is example code that illustrates how to use the Design Model API of FlexBuilder.
 */

package zorn.mxmlmodel.tests;

import java.util.Iterator;

import zorn.codemodel.common.ICodeModelConstants;
import zorn.codemodel.common.XMLName;
import zorn.mxmlmodel.IArray;
import zorn.mxmlmodel.IComponentInstance;
import zorn.mxmlmodel.IContainerInstance;
import zorn.mxmlmodel.IData;
import zorn.mxmlmodel.IMXMLItem;
import zorn.mxmlmodel.IMXMLModel;
import zorn.mxmlmodel.IOtherTag;
import zorn.mxmlmodel.IProperty;
import zorn.mxmlmodel.IState;
import zorn.mxmlmodel.IStringData;
import zorn.mxmlmodel.IStyle;
import zorn.mxmlmodel.IStyleProperty;
import zorn.mxmlmodel.IStyleRule;
import zorn.mxmlmodel.IUnknownTag;
import zorn.mxmlmodel.ModelEditException;

public class DesignModelExamples {

	/** This function illustrates some typical uses of the Design Model. 
	 * @param editor an MXMLEditor that has an open MXML document
	 * @return a dump of the document's structure, after we've finished modifying it 
	 * @throws Exception
	 */
	public String examples(IMXMLModel model) throws Exception {
		// setup
		IContainerInstance root = (IContainerInstance)model.getRoot();
		
		// add some new child items	
		addButton(root);
		IComponentInstance datagrid = addDataGrid(root);
		
		// find an item
		IMXMLItem button = model.findItemByID("aButton"); //$NON-NLS-1$
		StringBuffer output = new StringBuffer();
		dumpMXMLItem(button, EMPTY, output);
		
		// dump all the items in the model, starting from root
		dumpMXMLItem(root, EMPTY, output);
		
		// delete some items
		button.remove();
		datagrid.getProperty("x").remove(); //$NON-NLS-1$
		
		return output.toString();
	}

	private String getCategory(IMXMLItem item) {
		if (item instanceof IComponentInstance)
			return "ComponentInstance"; //$NON-NLS-1$
		if (item instanceof IData)
			return "Data"; //$NON-NLS-1$
		if (item instanceof IOtherTag)
			return "Other"; //$NON-NLS-1$
		if (item instanceof IProperty)
			return "Property"; //$NON-NLS-1$
		if (item instanceof IStringData)
			return "StringData"; //$NON-NLS-1$
		if (item instanceof IStyle)
			return "Style"; //$NON-NLS-1$
		if (item instanceof IStyleProperty)
			return "StyleProperty"; //$NON-NLS-1$
		if (item instanceof IStyleRule)
			return "StyleRule"; //$NON-NLS-1$
		if (item instanceof IUnknownTag)
			return "Unknown"; //$NON-NLS-1$
		
		return "???"; //$NON-NLS-1$
	}

	/** Writes a string summary of an MXML item to an output. This does
	 * not cover all possible information, just a few things.
	 */
	private void dumpMXMLItem(IMXMLItem item, String indent, StringBuffer output) {
		// this item's class
		output.append(indent);
		output.append(getCategory(item));

		// this item's name
		output.append(SPACE);
		output.append(item.getName().getName());
		
		// this item's id
		if (item.getID() != null) {
			output.append(SPACE);
			output.append(item.getID());
		}

		// if it's a component...
		if (item instanceof IComponentInstance){
			IComponentInstance componentInstance = (IComponentInstance)item;
			output.append(SPACE);
			output.append(componentInstance.getAsClass());
			IState state = componentInstance.getDefiningState();
			if (state != null) {
				output.append(" defined in state "); //$NON-NLS-1$
				output.append(state.getStateName());
			}
		}

		// if it's a style rule...
		if (item instanceof IStyleRule){
			IStyleRule styleRule = (IStyleRule)item;
			output.append(SPACE);
			output.append(styleRule.getRuleNames());
		}

		// if it's a component property ...
		if (item instanceof IProperty){
			IProperty property = (IProperty)item;
			output.append(SPACE);
			output.append(property.getStringValue());
		}

		// that's enough
		output.append(LINEEND);
		
		// output this item's children
		Iterator iter = item.getChildren().iterator();
		while(iter.hasNext()) {
			IMXMLItem child = (IMXMLItem)iter.next();
			dumpMXMLItem(child, indent + TAB, output);
		}
	}
	
	private void addButton(IContainerInstance container) throws ModelEditException {
		final XMLName buttonName = new XMLName(ICodeModelConstants.FLEX_URI, "Button"); //$NON-NLS-1$
		IComponentInstance button = container.newComponentInstance(buttonName);
		button.setID("aButton"); //$NON-NLS-1$
		button.setProperty("label", "Click Me"); //$NON-NLS-1$ //$NON-NLS-2$
	}

	private IComponentInstance addDataGrid(IContainerInstance container) throws ModelEditException {
		final XMLName dataGridName = new XMLName(ICodeModelConstants.FLEX_URI, "DataGrid"); //$NON-NLS-1$
		IComponentInstance datagrid = container.newComponentInstance(dataGridName);
		datagrid.setProperty("x", "123"); //$NON-NLS-1$ //$NON-NLS-2$
		
		// Use an Array accessor to add items to the datagrid's columns property
		IArray columnsArray = datagrid.getArrayAccessor("columns"); //$NON-NLS-1$
		final XMLName dataGridColumnName = new XMLName(ICodeModelConstants.FLEX_URI, "DataGridColumn"); //$NON-NLS-1$
		IComponentInstance column = (IComponentInstance)columnsArray.newChild(dataGridColumnName, null, IMXMLModel.DEFAULT);
		column.setProperty("columnName", "One");  //$NON-NLS-1$//$NON-NLS-2$
		column = (IComponentInstance)columnsArray.newChild(dataGridColumnName, null, IMXMLModel.DEFAULT);
		column.setProperty("columnName", "Two");  //$NON-NLS-1$//$NON-NLS-2$
		
		return datagrid;
	}
	
	private final String EMPTY = "";  //$NON-NLS-1$
	private final String SPACE = " ";  //$NON-NLS-1$
	private final String TAB = "\t";  //$NON-NLS-1$
	private final String LINEEND = "\r\n";  //$NON-NLS-1$
}