/***************************************************************************************************
 * Copyright (c) 2003, 2004 IBM Corporation and others. All rights reserved. This program and the
 * accompanying materials are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors: IBM Corporation - initial API and implementation
 **************************************************************************************************/
package org.eclipse.wst.common.internal.emf.resource;


import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EDataType;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.emf.ecore.impl.EStructuralFeatureImpl;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.wst.common.internal.emf.utilities.ExtendedEcoreUtil;
import org.eclipse.wst.common.internal.emf.utilities.FeatureValueConverter;


public class Translator {

	public final static int NO_STYLE = 0;
	public final static int DOM_ATTRIBUTE = 1;
	public final static int EMPTY_TAG = 1 << 1;
	public final static int CDATA_CONTENT = 1 << 2;
	/**
	 * Style bit that indicates that the end tag should NOT be indented; by default it is.
	 */
	public final static int END_TAG_NO_INDENT = 1 << 3;
	/**
	 * Style bit that indicates that booleans should NOT be converted as "True" and "False"; default
	 * is that they are
	 */
	public final static int BOOLEAN_LOWERCASE = 1 << 4;
	/**
	 * Style bit that indicates an enum value contains hyphens If this is true, then internally the
	 * hyphens are replaced with underscores
	 */
	public final static int ENUM_FEATURE_WITH_HYPHENS = 1 << 5;

	protected final static int OBJECT_MAP = 1 << 6;
	protected final static int BOOLEAN_FEATURE = 1 << 7;

	protected final static int SHARED_REFERENCE = 1 << 8;

	/**
	 * Indicates that the feature may be significant even if it is empty
	 */
	public final static int EMPTY_CONTENT_IS_SIGNIFICANT = 1 << 9;

	/**
	 * Used to indicate that feature is associated with a comment node
	 */
	protected final static int COMMENT_FEATURE = 1 << 10;

	/**
	 * If the value is null, then an eUnset() will be invoked on the feature
	 */
	public final static int UNSET_IF_NULL = 1 << 11;

	/**
	 * Return the element contents as a String if the feature is unresolveable (Used by the
	 * SourceLinkTranslator)
	 */
	public final static int STRING_RESULT_OK = 1 << 12;

	protected String[] fDOMNames;
	protected String fDOMPath = ""; //$NON-NLS-1$
	protected Map readAheadNames;
	protected int fStyle = NO_STYLE;
	protected EStructuralFeature feature;
	protected TranslatorPath[] fTranslatorPaths;
	protected EClass emfClass;
	protected String fNameSpace = ""; //$NON-NLS-1$
	// added by MDE
	protected String domNameAndPath = null;

	/**
	 * Indicates if any of the children of this Translator are themselves DependencyTranslators
	 */
	protected Boolean isDependencyParent;
	protected EStructuralFeature dependencyFeature;
	protected static EcorePackage ECORE_PACKAGE = EcorePackage.eINSTANCE;

	// Use this identifier for the DOMName when the attribute
	// value is to be extracted directly from the text of the node.
	// This is rare, but occurs in the web.xml in the case of a
	// WelcomeFile.
	static final public String TEXT_ATTRIBUTE_VALUE = "$TEXT_ATTRIBUTE_VALUE"; //$NON-NLS-1$

	static final public EStructuralFeature CONTAINER_FEATURE = new ContainerFeature();

	static final public EStructuralFeature ROOT_FEATURE = new RootFeature();

	protected static class ContainerFeature extends EStructuralFeatureImpl {
		protected ContainerFeature() {
			super();
		}
	}

	protected static class RootFeature extends EStructuralFeatureImpl {
		protected RootFeature() {
			super();
		}
	}

	public Translator findChild(String tagName, Object target, int versionID) {

		Translator result = null;
		Translator[] maps = getChildren(target, versionID);

		if (maps != null) {
			for (int i = 0; i < maps.length; i++) {
				Translator map = maps[i];
				if (map.isMapFor(tagName)) {
					result = map;
					break;
				}
			}
		}
		if (result == null) {
			VariableTranslatorFactory factory = getVariableTranslatorFactory();
			if (factory != null && factory.accepts(tagName)) {
				result = factory.create(tagName);
			}
		}
		return result;
	}

	/**
	 * Utility method to string together arrays of children
	 */
	public static Object[] concat(Object[] array1, Object[] array2) {
		Object[] result = (Object[]) java.lang.reflect.Array.newInstance(array1.getClass().getComponentType(), array1.length + array2.length);
		System.arraycopy(array1, 0, result, 0, array1.length);
		System.arraycopy(array2, 0, result, array1.length, array2.length);
		return result;
	}

	public static Object[] concat(Object[] array1, Object object2) {
		Object[] newArray = new Object[]{object2};
		return concat(array1, newArray);
	}

	public static Translator createParentAndTextAttributeTranslator(String domName, EStructuralFeature parentFeature, EStructuralFeature childFeature) {
		GenericTranslator parent = new GenericTranslator(domName, parentFeature, END_TAG_NO_INDENT);
		parent.setChildren(new Translator[]{new Translator(TEXT_ATTRIBUTE_VALUE, childFeature)});
		return parent;
	}

	public Translator(String domNameAndPath, EClass eClass) {
		initializeDOMNameAndPath(domNameAndPath);
		setEMFClass(eClass);
	}

	public Translator(String domNameAndPath, EStructuralFeature aFeature) {
		initializeDOMNameAndPath(domNameAndPath);
		setFeature(aFeature);
	}

	public Translator(String domNameAndPath, EStructuralFeature aFeature, EClass eClass) {
		this(domNameAndPath, aFeature);
		setEMFClass(emfClass);
	}

	public Translator(String domNameAndPath, EStructuralFeature aFeature, TranslatorPath path) {
		this(domNameAndPath, aFeature, new TranslatorPath[]{path});
	}

	public Translator(String domNameAndPath, EStructuralFeature aFeature, TranslatorPath[] paths) {
		initializeDOMNameAndPath(domNameAndPath);
		fTranslatorPaths = paths;
		setFeature(aFeature);
	}

	public Translator(String domNameAndPath, EStructuralFeature aFeature, int style) {
		initializeDOMNameAndPath(domNameAndPath);
		fStyle = style;
		setFeature(aFeature);
	}

	public static EcorePackage getEcorePackage() {
		return EcorePackage.eINSTANCE;
	}

	public String getDOMName(Object value) {
		return fDOMNames[0];
	}

	public String[] getDOMNames() {
		return fDOMNames;
	}

	public String getDOMPath() {
		return fDOMPath;
	}

	public boolean hasDOMPath() {
		return fDOMPath != null && fDOMPath.length() != 0;
	}

	public EStructuralFeature getFeature() {
		return feature;
	}

	/**
	 * Parse the DOM names and path out of <domNameAndPath>and set the appropriate fields.
	 */
	protected void initializeDOMNameAndPath(String domNameAndPathArg) {
		if (domNameAndPathArg == null)
			return;
		int inx = domNameAndPathArg.lastIndexOf('/');
		if (inx != -1) {
			fDOMNames = parseDOMNames(domNameAndPathArg.substring(inx + 1));
			fDOMPath = domNameAndPathArg.substring(0, inx);
		} else {
			fDOMNames = parseDOMNames(domNameAndPathArg);
			fDOMPath = ""; //$NON-NLS-1$
		}
		// added by MDE
		this.domNameAndPath = domNameAndPathArg;

	}

	/**
	 * Indicates whether the node should be written as an empty tag; eg, <distributable/>
	 */
	public boolean isCDATAContent() {
		return (fStyle & CDATA_CONTENT) != 0;
	}

	/**
	 * Indicates whether the DOMName represents a sub element name or an attribute name
	 * 
	 * @return boolean True if the DOMName is an attribute name.
	 */
	public boolean isDOMAttribute() {
		return (fStyle & DOM_ATTRIBUTE) != 0;
	}

	/**
	 * Indicates whether the node should be written as an empty tag; eg, <distributable/>
	 */
	public boolean isEmptyTag() {
		return (fStyle & EMPTY_TAG) != 0;
	}

	public boolean isBooleanUppercase() {
		return (fStyle & BOOLEAN_FEATURE) != 0 && (fStyle & BOOLEAN_LOWERCASE) == 0;
	}

	public boolean isBooleanFeature() {
		return (fStyle & BOOLEAN_FEATURE) != 0;
	}

	public boolean shouldIndentEndTag() {
		return (fStyle & END_TAG_NO_INDENT) == 0;
	}

	public boolean isEmptyContentSignificant() {
		return ((fStyle & EMPTY_TAG) != 0) || ((fStyle & EMPTY_CONTENT_IS_SIGNIFICANT) != 0);
	}

	/**
	 * Returns true if this map is to another MOF object (not a primitive)
	 */
	public boolean isObjectMap() {
		return (fStyle & OBJECT_MAP) != 0;
	}

	/**
	 * Returns true if this map is for a shared reference
	 */
	public boolean isShared() {
		return (fStyle & SHARED_REFERENCE) != 0;
	}

	public boolean isEnumWithHyphens() {
		return (fStyle & ENUM_FEATURE_WITH_HYPHENS) != 0;
	}

	/**
	 * Indicates whether the map represents a case where the text of the DOMNode represents the
	 * objects one and only attribute value. An example of this case is a <welcome-file>file.txt
	 * </welcome-file>.
	 */
	public boolean isDOMTextValue() {
		return fDOMNames[0] == TEXT_ATTRIBUTE_VALUE;
	}

	/**
	 * Indicates whether the id is the mof attribute that should be set.
	 */
	public boolean isIDMap() {
		return false;
	}

	/**
	 * Indicates whether the id is the mof attribute that should be set.
	 */
	public boolean isLinkMap() {
		return fTranslatorPaths != null;
	}

	public boolean isTargetLinkMap() {
		return isLinkMap() && !isObjectMap();
	}

	/**
	 * Return true if this map is the one representing a node with the name <domName>. By default
	 * this method simply compares the DOM name of the map against the <domName>parameter
	 * 
	 * @return boolean
	 * @param domName
	 *            java.lang.String
	 */
	public boolean isMapFor(String domName) {
		if (domName.equals(getDOMPath()))
			return true;
		for (int i = 0; i < fDOMNames.length; i++) {
			if (domName.equals(fDOMNames[i]))
				return true;
		}
		return false;
	}

	public boolean isMapFor(Object aFeature, Object oldValue, Object newValue) {
		return feature == aFeature;
	}

	/**
	 * Indicates whether feature being mapped is a collection.
	 * 
	 * @return boolean True if the feature is multi valued.
	 */
	public boolean isMultiValued() {
		if (feature != null)
			return feature.isMany();
		return false;
	}

	/**
	 * Parses comma separated names from <domNamesString>. Returns an array containing the names.
	 * 
	 * @return java.lang.String[]
	 * @param domNamesString
	 *            java.lang.String
	 */
	protected String[] parseDOMNames(String domNamesString) {
		int startInx = 0;
		int inx = domNamesString.indexOf(',');
		ArrayList results = new ArrayList(1);
		while (inx != -1) {
			results.add(domNamesString.substring(startInx, inx));
			startInx = inx + 1;
			inx = domNamesString.indexOf(',', startInx);
		}
		if (startInx == 0)
			results.add(domNamesString);
		else
			results.add(domNamesString.substring(startInx));
		return (String[]) results.toArray(new String[results.size()]);
	}

	public String toString() {
		StringBuffer sb = new StringBuffer();
		String cn = getClass().getName();
		int i = cn.lastIndexOf('.');
		cn = cn.substring(++i, cn.length());
		sb.append(cn);
		sb.append('(');
		sb.append(fDOMNames[0]);
		for (int j = 1; j < fDOMNames.length; j++) {
			sb.append('|');
			sb.append(fDOMNames[j]);
		}
		sb.append(',');
		sb.append(hashCode());
		sb.append(')');
		return sb.toString();
	}

	/**
	 * Gets the TranslatorPath.
	 * 
	 * @return Returns a TranslatorPath
	 */
	public TranslatorPath[] getTranslatorPaths() {
		return fTranslatorPaths;
	}

	/*
	 * @see Object#equals(Object)
	 */
	public boolean equals(Object object) {
		if (!(object instanceof Translator))
			return false;
		Translator mapInfo = (Translator) object;
		return fDOMNames.equals(mapInfo.getDOMNames()) && (feature == null && mapInfo.getFeature() == null || feature.equals(mapInfo.getFeature()));
	}

	/**
	 * Returns the isManagedByParent.
	 * 
	 * @return boolean
	 */
	public boolean isManagedByParent() {
		return getChildren(null, -1) == null;
	}

	/*
	 * In the 99% case there is only one node name to be concerned with, but subclasses can override
	 * for the cases where multiple dom names map to one feature
	 */
	public EObject createEMFObject(String nodeName, String readAheadName) {
		if (emfClass == null) {
			if (feature == null)
				return null;
			if (isObjectMap())
				return createEMFObject(feature);
		}
		return createEMFObject(emfClass);
	}

	public static EObject createEMFObject(EStructuralFeature aFeature) {
		if (aFeature == null)
			return null;

		return createEMFObject(((EReference) aFeature).getEReferenceType());
	}

	public static EObject createEMFObject(EClass anEClass) {
		if (anEClass == null)
			return null;
		return anEClass.getEPackage().getEFactoryInstance().create(anEClass);
	}

	public void setTextValueIfNecessary(String textValue, Notifier owner, int versionId) {
		Translator textTranslator = this.findChild(Translator.TEXT_ATTRIBUTE_VALUE, owner, versionId);
		if (textTranslator != null) {
			Object objectValue = textTranslator.convertStringToValue(textValue, (EObject) owner);
			textTranslator.setMOFValue(owner, objectValue);
		}
	}

	/**
	 * Check to see if feature is valid on a particular mofObject.
	 * 
	 * @return boolean Return true if the feature specified exists on the MOF object.
	 * @param emfObject
	 *            org.eclipse.emf.ecore.EObject
	 */
	public boolean featureExists(EObject emfObject) {
		if (feature == null)
			return false;

		return emfObject.eClass().getEStructuralFeature(feature.getName()) != null;
	}

	/**
	 * Translators which do not have a feature should override this method with custom behavior.
	 */
	public String extractStringValue(EObject emfObject) {
		if (isEmptyTag() && feature == null)
			return ""; //Fake it out with a value //$NON-NLS-1$
		return null;
	}

	public Object convertStringToValue(String nodeName, String readAheadName, String value, Notifier owner) {
		Object result = null;
		try {

			if (!this.isManagedByParent()) {
				result = createEMFObject(nodeName, readAheadName);
			} else {
				result = convertStringToValue(value, (EObject) owner);
			}

		} catch (ClassCastException cce) {

		}
		return result;
	}

	/**
	 * Converts a string value to the appropriate type.
	 * 
	 * @return java.lang.Object The converted value
	 * @param strValue
	 *            java.lang.String The string to convert.
	 */
	public Object convertStringToValue(String strValue, EObject owner) {
		if (feature == null)
			return strValue;
		if (strValue != null) {
			if (isEnumWithHyphens())
				strValue = strValue.replace('-', '_');
			if (!isCDATAContent()) {
				strValue = strValue.trim();
			}
		}
		Object value = FeatureValueConverter.DEFAULT.convertValue(strValue, feature);
		if (value == null) {
			if (isEmptyTag() && !isDOMAttribute() && !isDOMTextValue() && isBooleanFeature())
				return Boolean.TRUE;
			EObject convertToType = feature.getEType();
			if (convertToType == null)
				value = strValue;
			else if (convertToType.equals(getEcorePackage().getEString())) {
				value = ""; //$NON-NLS-1$
			}
		}
		return value;
	}

	/**
	 * Converts a value of a specified type to a string value. Subclasses may override for special
	 * cases where special conversion needs to occur based on the feature and or object type.
	 * 
	 * @return String The converted value
	 * @param value
	 *            java.lang.Object The object to convert.
	 */
	public String convertValueToString(Object value, EObject owner) {
		if (isEmptyTag() || value == null)
			return null;
		else if (isEnumWithHyphens())
			return value.toString().replace('_', '-');
		else if (isBooleanUppercase())
			return ((Boolean) value).booleanValue() ? "True" : "False"; //$NON-NLS-1$ //$NON-NLS-2$

		return value.toString();
	}

	public Translator[] getVariableChildren(Notifier target, int version) {
		Translator[] results = null;
		VariableTranslatorFactory factory = getVariableTranslatorFactory();
		if (factory != null) {
			List variableTranslators = factory.create(target);
			if (variableTranslators != null && variableTranslators.size() > 0) {
				Object[] vtoa = variableTranslators.toArray();

				results = new Translator[vtoa.length];
				for (int i = 0; i < results.length; i++)
					results[i] = (Translator) vtoa[i];
			}

		}
		if (results == null)
			results = new Translator[0];
		return results;
	}

	/**
	 * Returns null by default; subclasses should override to return specific children
	 */
	public Translator[] getChildren(Object target, int versionID) {
		return getChildren();
	}

	protected Translator[] getChildren() {
		return null;
	}

	/**
	 * Return the list of MOF children that currently exist for the values of an attribute.
	 */
	public List getMOFChildren(EObject mofObject) {
		if (feature == null)
			return Collections.EMPTY_LIST;
		Object value = getMOFValue(mofObject);
		List result = Collections.EMPTY_LIST;
		if (isMultiValued())
			result = (List) value;
		else if (value != null)
			result = Collections.singletonList(value);
		return result;
	}

	public Object getMOFValue(EObject mofObject) {
		if (feature == null)
			return null;
		return mofObject.eGet(feature);
	}

	/**
	 * Sets a value of a feature in a mof object.
	 */
	public void setMOFValue(Notifier owner, Object value, int newIndex) {
		if (feature != null) {
			if ((fStyle & UNSET_IF_NULL) != 0 && value == null)
				ExtendedEcoreUtil.eUnsetOrRemove((EObject) owner, feature, value);
			else
				ExtendedEcoreUtil.eSetOrAdd((EObject) owner, feature, value, newIndex);
		}
	}

	public void setMOFValue(Notifier owner, Object value) {
		if (owner instanceof EObject) {
			setMOFValue((EObject) owner, value);
		} else if (owner instanceof Resource) {
			setMOFValue((Resource) owner, value);
		}
	}

	public void setMOFValue(EObject emfObject, Object value) {
		//		if (feature != null)
		//			emfObject.eSet(feature, value);
		setMOFValue(emfObject, value, -1);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.etools.emf2xml.impl.Translator#setMOFValue(org.eclipse.emf.ecore.EObject,
	 *      java.lang.Object)
	 */
	public void setMOFValue(Resource res, Object value) {
		if (res != null && value != null)
			res.getContents().add(value);
	}

	public void removeMOFValue(Notifier owner, Object value) {
		if (feature != null)
			ExtendedEcoreUtil.eUnsetOrRemove((EObject) owner, feature, value);
	}

	public boolean isSetMOFValue(EObject emfObject) {
		boolean isSet = feature != null && emfObject.eIsSet(feature);
		if (isEmptyTag())
			return isSet && ((Boolean) emfObject.eGet(feature)).booleanValue();
		return isSet;
	}

	public void unSetMOFValue(EObject emfObject) {
		if (feature != null)
			emfObject.eUnset(feature);
	}

	public void clearList(EObject mofObject) {
		if (feature != null)
			((List) mofObject.eGet(feature)).clear();
	}

	protected void setFeature(EStructuralFeature aFeature) {
		this.feature = aFeature;
		if (feature == null)
			return;
		//This way an instance check happens only once
		if (aFeature instanceof EReference) {
			fStyle |= OBJECT_MAP;
			if (!((EReference) aFeature).isContainment())
				fStyle |= SHARED_REFERENCE;
		}

		if (getEcorePackage().getEBoolean() == feature.getEType())
			fStyle |= BOOLEAN_FEATURE;
	}

	protected void setEMFClass(EClass anEClass) {
		this.emfClass = anEClass;
		if (anEClass != null)
			fStyle |= OBJECT_MAP;

	}

	public boolean hasReadAheadNames() {
		return readAheadNames != null && !readAheadNames.isEmpty();
	}

	/**
	 * Return the read ahead names, if they are defined, for a given parent node name. This is used
	 * when creation of a specific EMF object is dependent on the value of a child node.
	 */
	public ReadAheadHelper getReadAheadHelper(String parentName) {
		if (readAheadNames == null)
			return null;
		return (ReadAheadHelper) readAheadNames.get(parentName);
	}

	public void addReadAheadHelper(ReadAheadHelper helper) {
		if (readAheadNames == null)
			readAheadNames = new HashMap(3);
		readAheadNames.put(helper.getParentDOMName(), helper);
	}

	public boolean isDependencyChild() {
		return false;
	}

	/**
	 * @return
	 */
	public boolean isDependencyParent() {
		if (isDependencyParent == null) {
			isDependencyParent = Boolean.FALSE;
			Translator[] theChildren = getChildren(null, -1);
			if (theChildren != null) {
				for (int i = 0; i < theChildren.length; i++) {
					//For now we assume one
					if (theChildren[i].isDependencyChild()) {
						isDependencyParent = Boolean.TRUE;
						dependencyFeature = theChildren[i].getDependencyFeature();
					}
				}
			}
		}
		return isDependencyParent.booleanValue();
	}

	/**
	 * @return
	 */
	public EStructuralFeature getDependencyFeature() {
		return dependencyFeature;
	}

	public EObject basicGetDependencyObject(EObject parent) {
		return (EObject) parent.eGet(dependencyFeature);
	}

	/**
	 * Use when the DOM path is not null, and there are no children. Default is false, but
	 * subclasses may wish to override
	 */
	public boolean shouldRenderEmptyDOMPath(EObject eObject) {
		return isEmptyContentSignificant();
	}

	/**
	 * Use when the translator tolerates parent nodes that relate to the DOM path, and no children;
	 * default is do nothing
	 */
	public void setMOFValueFromEmptyDOMPath(EObject eObject) {

	}

	/**
	 * Namespace for the attributes
	 * 
	 * @return
	 */
	public String getNameSpace() {
		return fNameSpace;
	}

	/**
	 * Set the namespace for the dom attribute
	 * 
	 * @param string
	 */
	public void setNameSpace(String string) {
		fNameSpace = string;
	}

	public VariableTranslatorFactory getVariableTranslatorFactory() {
		if (isObjectMap())
			return DefaultTranslatorFactory.INSTANCE;
		return null;
	}

	public boolean isEnumFeature() {
		return feature != null && ECORE_PACKAGE.getEEnum().isInstance(feature.getEType());
	}

	public boolean isUnsettable() {
		return feature != null && feature.isUnsettable();
	}

	public boolean isDataType() {
		return feature != null && feature.getEType() instanceof EDataType;
	}

	/**
	 * @return
	 */
	public boolean isComment() {
		return (fStyle & COMMENT_FEATURE) != 0;
	}

}