/*******************************************************************************
 * Copyright (c) 2001, 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
 *     Jens Lukowski/Innoopract - initial renaming/restructuring
 *     
 *******************************************************************************/
package org.eclipse.wst.xml.core.internal.document;



import org.eclipse.wst.xml.core.internal.commentelement.impl.CommentElementRegistry;
import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
import org.eclipse.wst.xml.core.internal.provisional.IXMLCharEntity;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMAttr;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
import org.eclipse.wst.xml.core.internal.provisional.document.ISourceGenerator;
import org.w3c.dom.Attr;
import org.w3c.dom.CDATASection;
import org.w3c.dom.Comment;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
import org.w3c.dom.EntityReference;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.ProcessingInstruction;
import org.w3c.dom.Text;


/** 
 */
public class XMLGeneratorImpl implements ISourceGenerator {
	private static final String CDATA_CLOSE = "]]>";//$NON-NLS-1$
	private static final String CDATA_OPEN = "<![CDATA[";//$NON-NLS-1$
	private static final String COMMENT_CLOSE = "-->";//$NON-NLS-1$
	private static final String COMMENT_OPEN = "<!--";//$NON-NLS-1$
	private static final String DOCTYPE_OPEN = "<!DOCTYPE";//$NON-NLS-1$
	private static final String EMPTY_CLOSE = " />";//$NON-NLS-1$
	private static final String END_OPEN = "</";//$NON-NLS-1$

	private static XMLGeneratorImpl instance = null;
	private static final String PI_CLOSE = "?>";//$NON-NLS-1$
	private static final String PI_OPEN = "<?";//$NON-NLS-1$
	private static final String PUBLIC_ID = "PUBLIC";//$NON-NLS-1$
	private static final String SSI_PREFIX = "ssi";//$NON-NLS-1$
	//private static final String SSI_FEATURE = "SSI";//$NON-NLS-1$
	private static final String SSI_TOKEN = "#";//$NON-NLS-1$
	private static final String SYSTEM_ID = "SYSTEM";//$NON-NLS-1$
	private static final String TAG_CLOSE = ">";//$NON-NLS-1$

	/**
	 */
	public synchronized static ISourceGenerator getInstance() {
		if (instance == null)
			instance = new XMLGeneratorImpl();
		return instance;
	}

	/**
	 */
	//private boolean isCommentTag(XMLElement element) {
	//	if (element == null) return false;
	//	DocumentImpl document = (DocumentImpl)element.getOwnerDocument();
	//	if (document == null) return false;
	//	DocumentTypeAdapter adapter = document.getDocumentTypeAdapter();
	//	if (adapter == null) return false;
	//	if (!adapter.hasFeature(SSI_FEATURE)) return false;
	//	String prefix = element.getPrefix();
	//	return (prefix != null && prefix.equals(SSI_PREFIX));
	//}
	/**
	 * Helper to modify the tag name in sub-classes
	 */
	private static void setTagName(Element element, String tagName) {
		if (element == null || tagName == null)
			return;
		((ElementImpl) element).setTagName(tagName);
	}

	/**
	 * XMLModelGenerator constructor
	 */
	private XMLGeneratorImpl() {
		super();
	}

	/**
	 */
	public String generateAttrName(Attr attr) {
		if (attr == null)
			return null;
		String attrName = attr.getName();
		if (attrName == null)
			return null;
		if (attrName.startsWith(JSPTag.TAG_OPEN)) {
			if (!attrName.endsWith(JSPTag.TAG_CLOSE)) {
				// close JSP
				return (attrName + JSPTag.TAG_CLOSE);
			}
		}
		if (((IDOMAttr) attr).isGlobalAttr() && CMNodeUtil.getAttributeDeclaration(attr) != null) {
			switch (getAttrNameCase(attr)) {
				case DocumentTypeAdapter.UPPER_CASE :
					attrName = attrName.toUpperCase();
					break;
				case DocumentTypeAdapter.LOWER_CASE :
					attrName = attrName.toLowerCase();
					break;
				default :
					// ASIS_CASE
					break;
			}
		}
		return attrName;
	}

	/**
	 */
	public String generateAttrValue(Attr attr) {
		return generateAttrValue(attr, (char) 0); // no quote preference
	}

	/**
	 */
	public String generateAttrValue(Attr attr, char quote) {
		if (attr == null)
			return null;
		String name = attr.getName();
		SourceValidator validator = new SourceValidator(attr);
		String value = validator.convertSource(((IDOMNode) attr).getValueSource());
		if (value == null || value.length() == 0) {
			if (name != null && name.startsWith(JSPTag.TAG_OPEN))
				return null;
			if (isBooleanAttr(attr)) {
				if (((AttrImpl) attr).isXMLAttr()) {
					// generate the name as value
					value = attr.getName();
				} else {
					// not to generate '=' and value for HTML boolean
					return null;
				}
			}
		}
		return generateAttrValue(value, quote);
	}

	/**
	 */
	public String generateAttrValue(String value, char quote) {
		// assume the valid is already validated not to include both quotes
		if (quote == '"') {
			if ((value != null) && (value.indexOf('"') >= 0))
				quote = '\''; // force
		} else if (quote == '\'') {
			if ((value != null) && (value.indexOf('\'') >= 0))
				quote = '"'; // force
		} else { // no preference
			if ((value != null) && (value.indexOf('"') < 0))
				quote = '"';
			else
				quote = '\'';
		}

		int length = (value == null ? 0 : value.length());
		StringBuffer buffer = new StringBuffer(length + 2);
		buffer.append(quote);
		if (value != null)
			buffer.append(value);
		buffer.append(quote);
		return buffer.toString();
	}

	/**
	 * generateCDATASection method
	 * 
	 * @return java.lang.String
	 * @param comment
	 *            org.w3c.dom.CDATASection
	 */
	public String generateCDATASection(CDATASection cdata) {
		if (cdata == null)
			return null;

		String data = cdata.getData();
		int length = (data != null ? data.length() : 0);
		StringBuffer buffer = new StringBuffer(length + 16);
		buffer.append(CDATA_OPEN);
		if (data != null)
			buffer.append(data);
		buffer.append(CDATA_CLOSE);
		return buffer.toString();
	}

	/**
	 * generateChild method
	 * 
	 * @return java.lang.String
	 * @param org.w3c.dom.Node
	 */
	public String generateChild(Node parentNode) {
		if (parentNode == null)
			return null;
		if (!parentNode.hasChildNodes())
			return null;

		StringBuffer buffer = new StringBuffer();
		for (Node child = parentNode.getFirstChild(); child != null; child = child.getNextSibling()) {
			String childSource = generateSource(child);
			if (childSource != null)
				buffer.append(childSource);
		}
		return buffer.toString();
	}

	/**
	 */
	public String generateCloseTag(Node node) {
		if (node == null)
			return null;

		switch (node.getNodeType()) {
			case Node.ELEMENT_NODE : {
				ElementImpl element = (ElementImpl) node;
				if (element.isCommentTag()) {
					if (element.isJSPTag())
						return JSPTag.COMMENT_CLOSE;
					return COMMENT_CLOSE;
				}
				if (element.isJSPTag())
					return JSPTag.TAG_CLOSE;
				if (element.isEmptyTag())
					return EMPTY_CLOSE;
				return TAG_CLOSE;
			}
			case Node.COMMENT_NODE : {
				CommentImpl comment = (CommentImpl) node;
				if (comment.isJSPTag())
					return JSPTag.COMMENT_CLOSE;
				return COMMENT_CLOSE;
			}
			case Node.DOCUMENT_TYPE_NODE :
				return TAG_CLOSE;
			case Node.PROCESSING_INSTRUCTION_NODE :
				return PI_CLOSE;
			case Node.CDATA_SECTION_NODE :
				return CDATA_CLOSE;
			default :
				break;
		}

		return null;
	}

	/**
	 * generateComment method
	 * 
	 * @return java.lang.String
	 * @param comment
	 *            org.w3c.dom.Comment
	 */
	public String generateComment(Comment comment) {
		if (comment == null)
			return null;

		String data = comment.getData();
		int length = (data != null ? data.length() : 0);
		StringBuffer buffer = new StringBuffer(length + 8);
		CommentImpl impl = (CommentImpl) comment;
		if (!impl.isJSPTag())
			buffer.append(COMMENT_OPEN);
		else
			buffer.append(JSPTag.COMMENT_OPEN);
		if (data != null)
			buffer.append(data);
		if (!impl.isJSPTag())
			buffer.append(COMMENT_CLOSE);
		else
			buffer.append(JSPTag.COMMENT_CLOSE);
		return buffer.toString();
	}

	/**
	 * generateDoctype method
	 * 
	 * @return java.lang.String
	 * @param docType
	 *            org.w3c.dom.DocumentType
	 */
	public String generateDoctype(DocumentType docType) {
		if (docType == null)
			return null;

		String name = docType.getName();
		int length = (name != null ? name.length() : 0);
		StringBuffer buffer = new StringBuffer(length + 16);
		buffer.append(DOCTYPE_OPEN);
		buffer.append(' ');
		if (name != null)
			buffer.append(name);
		DocumentTypeImpl dt = (DocumentTypeImpl) docType;
		String publicID = dt.getPublicId();
		String systemID = dt.getSystemId();
		if (publicID != null) {
			buffer.append(' ');
			buffer.append(PUBLIC_ID);
			buffer.append(' ');
			buffer.append('"');
			buffer.append(publicID);
			buffer.append('"');
			if (systemID != null) {
				buffer.append(' ');
				buffer.append('"');
				buffer.append(systemID);
				buffer.append('"');
			}
		} else {
			if (systemID != null) {
				buffer.append(' ');
				buffer.append(SYSTEM_ID);
				buffer.append(' ');
				buffer.append('"');
				buffer.append(systemID);
				buffer.append('"');
			}
		}
		buffer.append('>');
		return buffer.toString();
	}

	/**
	 * generateElement method
	 * 
	 * @return java.lang.String
	 * @param element
	 *            Element
	 */
	public String generateElement(Element element) {
		if (element == null)
			return null;

		// if empty tag is preferrable, generate as empty tag
		ElementImpl impl = (ElementImpl) element;
		if (impl.preferEmptyTag())
			impl.setEmptyTag(true);

		StringBuffer buffer = new StringBuffer();
		String startTag = generateStartTag(element);
		if (startTag != null)
			buffer.append(startTag);
		String child = generateChild(element);
		if (child != null)
			buffer.append(child);
		String endTag = generateEndTag(element);
		if (endTag != null)
			buffer.append(endTag);
		return buffer.toString();
	}

	/**
	 * generateEndTag method
	 * 
	 * @return java.lang.String
	 * @param element
	 *            org.w3c.dom.Element
	 */
	public String generateEndTag(Element element) {
		if (element == null)
			return null;

		ElementImpl impl = (ElementImpl) element;

		// first check if tag adapter exists
		TagAdapter adapter = (TagAdapter) impl.getExistingAdapter(TagAdapter.class);
		if (adapter != null) {
			String endTag = adapter.getEndTag(impl);
			if (endTag != null)
				return endTag;
		}

		if (impl.isEmptyTag())
			return null;
		if (!impl.isContainer())
			return null;
		if (impl.isJSPTag())
			return JSPTag.TAG_CLOSE;

		String tagName = generateTagName(element);
		int length = (tagName != null ? tagName.length() : 0);
		StringBuffer buffer = new StringBuffer(length + 4);
		buffer.append(END_OPEN);
		if (tagName != null)
			buffer.append(tagName);
		buffer.append('>');
		return buffer.toString();
	}

	/**
	 * generateEntityRef method
	 * 
	 * @return java.lang.String
	 * @param entityRef
	 *            org.w3c.dom.EntityReference
	 */
	public String generateEntityRef(EntityReference entityRef) {
		if (entityRef == null)
			return null;

		String name = entityRef.getNodeName();
		int length = (name != null ? name.length() : 0);
		StringBuffer buffer = new StringBuffer(length + 4);
		buffer.append('&');
		if (name != null)
			buffer.append(name);
		buffer.append(';');
		return buffer.toString();
	}

	/**
	 * generatePI method
	 * 
	 * @return java.lang.String
	 * @param pi
	 *            org.w3c.dom.ProcessingInstruction
	 */
	public String generatePI(ProcessingInstruction pi) {
		if (pi == null)
			return null;

		String target = pi.getTarget();
		String data = pi.getData();
		int length = (target != null ? target.length() : 0);
		if (data != null)
			length += data.length();
		StringBuffer buffer = new StringBuffer(length + 8);
		buffer.append(PI_OPEN);
		if (target != null)
			buffer.append(target);
		buffer.append(' ');
		if (data != null)
			buffer.append(data);
		buffer.append(PI_CLOSE);
		return buffer.toString();
	}

	/**
	 * generateSource method
	 * 
	 * @return java.lang.String
	 * @param node
	 *            org.w3c.dom.Node
	 */
	public String generateSource(Node node) {
		switch (node.getNodeType()) {
			case Node.ELEMENT_NODE :
				return generateElement((Element) node);
			case Node.TEXT_NODE :
				return generateText((Text) node);
			case Node.COMMENT_NODE :
				return generateComment((Comment) node);
			case Node.DOCUMENT_TYPE_NODE :
				return generateDoctype((DocumentType) node);
			case Node.PROCESSING_INSTRUCTION_NODE :
				return generatePI((ProcessingInstruction) node);
			case Node.CDATA_SECTION_NODE :
				return generateCDATASection((CDATASection) node);
			case Node.ENTITY_REFERENCE_NODE :
				return generateEntityRef((EntityReference) node);
			default :
				// DOCUMENT
				break;
		}
		return generateChild(node);
	}

	/**
	 * generateStartTag method
	 * 
	 * @return java.lang.String
	 * @param element
	 *            Element
	 */
	public String generateStartTag(Element element) {
		if (element == null)
			return null;

		ElementImpl impl = (ElementImpl) element;

		if (impl.isJSPTag()) {
			// check if JSP content type and JSP Document
			IDOMDocument document = (IDOMDocument) element.getOwnerDocument();
			if (document != null && document.isJSPType()) {
				if (document.isJSPDocument() && !impl.hasChildNodes()) {
					impl.setJSPTag(false);
				}
			} else {
				impl.setJSPTag(false);
			}
		}
		if (impl.isCommentTag() && impl.getExistingAdapter(TagAdapter.class) == null) {
			CommentElementRegistry registry = CommentElementRegistry.getInstance();
			registry.setupCommentElement(impl);
		}

		// first check if tag adapter exists
		TagAdapter adapter = (TagAdapter) impl.getExistingAdapter(TagAdapter.class);
		if (adapter != null) {
			String startTag = adapter.getStartTag(impl);
			if (startTag != null)
				return startTag;
		}

		StringBuffer buffer = new StringBuffer();

		if (impl.isCommentTag()) {
			if (impl.isJSPTag())
				buffer.append(JSPTag.COMMENT_OPEN);
			else
				buffer.append(COMMENT_OPEN);
			String tagName = generateTagName(element);
			if (tagName != null)
				buffer.append(tagName);
		} else if (impl.isJSPTag()) {
			buffer.append(JSPTag.TAG_OPEN);
			String tagName = generateTagName(element);
			if (tagName != null)
				buffer.append(tagName);
			if (impl.isContainer())
				return buffer.toString(); // JSP container
		} else {
			buffer.append('<');
			String tagName = generateTagName(element);
			if (tagName != null)
				buffer.append(tagName);
		}

		NamedNodeMap attributes = element.getAttributes();
		int length = attributes.getLength();
		for (int i = 0; i < length; i++) {
			AttrImpl attr = (AttrImpl) attributes.item(i);
			if (attr == null)
				continue;
			buffer.append(' ');
			String attrName = generateAttrName(attr);
			if (attrName != null)
				buffer.append(attrName);
			String attrValue = generateAttrValue(attr);
			if (attrValue != null) {
				// attr name only for HTML boolean and JSP
				buffer.append('=');
				buffer.append(attrValue);
			}
		}

		String closeTag = generateCloseTag(element);
		if (closeTag != null)
			buffer.append(closeTag);

		return buffer.toString();
	}

	/**
	 */
	public String generateTagName(Element element) {
		if (element == null)
			return null;
		IDOMElement xe = (IDOMElement) element;
		String tagName = element.getTagName();
		if (tagName == null)
			return null;
		if (xe.isJSPTag()) {
			if (tagName.equals(JSPTag.JSP_EXPRESSION))
				return JSPTag.EXPRESSION_TOKEN;
			if (tagName.equals(JSPTag.JSP_DECLARATION))
				return JSPTag.DECLARATION_TOKEN;
			if (tagName.equals(JSPTag.JSP_DIRECTIVE))
				return JSPTag.DIRECTIVE_TOKEN;
			if (tagName.startsWith(JSPTag.JSP_DIRECTIVE)) {
				int offset = JSPTag.JSP_DIRECTIVE.length() + 1; // after '.'
				return (JSPTag.DIRECTIVE_TOKEN + tagName.substring(offset));
			}
			return (xe.isCommentTag()) ? tagName : null;
		} else if (tagName.startsWith(JSPTag.TAG_OPEN)) {
			if (!tagName.endsWith(JSPTag.TAG_CLOSE)) {
				// close JSP
				return (tagName + JSPTag.TAG_CLOSE);
			}
		} else if (xe.isCommentTag()) {
			String prefix = element.getPrefix();
			if (prefix.equals(SSI_PREFIX)) {
				return (SSI_TOKEN + element.getLocalName());
			}
		} else {
			if (!xe.isJSPTag() && xe.isGlobalTag() && // global tag
						CMNodeUtil.getElementDeclaration(xe) != null) {
				String newName = tagName;
				switch (getTagNameCase(xe)) {
					case DocumentTypeAdapter.UPPER_CASE :
						newName = tagName.toUpperCase();
						break;
					case DocumentTypeAdapter.LOWER_CASE :
						newName = tagName.toLowerCase();
						break;
				}
				if (newName != tagName) {
					tagName = newName;
					setTagName(element, tagName);
				}
			}
		}
		return tagName;
	}

	/**
	 * generateText method
	 * 
	 * @return java.lang.String
	 * @param text
	 *            org.w3c.dom.Text
	 */
	public String generateText(Text text) {
		if (text == null)
			return null;
		TextImpl impl = (TextImpl) text;
		String source = impl.getTextSource();
		if (source != null)
			return source;
		return generateTextData(text, impl.getData());
	}

	/**
	 */
	public String generateTextData(Text text, String data) {
		if (data == null)
			return null;
		if (text == null)
			return null;
		TextImpl impl = (TextImpl) text;
		if (impl.isJSPContent() || impl.isCDATAContent()) {
			return new SourceValidator(impl).convertSource(data);
		}
		String source = data;

		// convert special characters to character entities
		StringBuffer buffer = null;
		int offset = 0;
		int length = data.length();
		for (int i = 0; i < length; i++) {
			String name = getCharName(data.charAt(i));
			if (name == null)
				continue;
			if (buffer == null)
				buffer = new StringBuffer(length + 8);
			if (i > offset)
				buffer.append(data.substring(offset, i));
			buffer.append('&');
			buffer.append(name);
			buffer.append(';');
			offset = i + 1;
		}
		if (buffer != null) {
			if (length > offset)
				buffer.append(data.substring(offset));
			source = buffer.toString();
		}

		if (source == null || source.length() == 0)
			return null;
		return source;
	}

	/**
	 */
	private int getAttrNameCase(Attr attr) {
		DocumentImpl document = (DocumentImpl) attr.getOwnerDocument();
		if (document == null)
			return DocumentTypeAdapter.STRICT_CASE;
		DocumentTypeAdapter adapter = (DocumentTypeAdapter) document.getAdapterFor(DocumentTypeAdapter.class);
		if (adapter == null)
			return DocumentTypeAdapter.STRICT_CASE;
		return adapter.getAttrNameCase();
	}

	/**
	 */
	private String getCharName(char c) {
		switch (c) {
			case '<' :
				return IXMLCharEntity.LT_NAME;
			case '>' :
				return IXMLCharEntity.GT_NAME;
			case '&' :
				return IXMLCharEntity.AMP_NAME;
			case '"' :
				return IXMLCharEntity.QUOT_NAME;
		}
		return null;
	}

	/**
	 */
	private int getTagNameCase(Element element) {
		DocumentImpl document = (DocumentImpl) element.getOwnerDocument();
		if (document == null)
			return DocumentTypeAdapter.STRICT_CASE;
		DocumentTypeAdapter adapter = (DocumentTypeAdapter) document.getAdapterFor(DocumentTypeAdapter.class);
		if (adapter == null)
			return DocumentTypeAdapter.STRICT_CASE;
		return adapter.getTagNameCase();
	}

	/**
	 */
	private boolean isBooleanAttr(Attr attr) {
		if (attr == null)
			return false;
		CMAttributeDeclaration decl = CMNodeUtil.getAttributeDeclaration(attr);
		if (decl == null)
			return false;
		CMDataType type = decl.getAttrType();
		if (type == null)
			return false;
		String values[] = type.getEnumeratedValues();
		if (values == null)
			return false;
		return (values.length == 1 && values[0].equals(decl.getAttrName()));
	}
}
