/*******************************************************************************
 * Copyright (c) 1998, 2008 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:
 *    Goh KONDOH - initial API and implementation
 *******************************************************************************/

package org.eclipse.actf.model.dom.sgml;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.URL;
import java.util.Hashtable;

import org.w3c.dom.Attr;
import org.w3c.dom.CDATASection;
import org.w3c.dom.Comment;
import org.w3c.dom.DOMConfiguration;
import org.w3c.dom.DOMException;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentFragment;
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.NodeList;
import org.w3c.dom.ProcessingInstruction;
import org.w3c.dom.Text;

/**
 * Root node is a instance of this class.
 */
public class SGMLDocument extends SGMLParentNode implements Document {
	/**
	 * @serial
	 */
	private Element documentElement = null;

	/**
	 * @serial
	 */
	private DocumentType doctype = null;

	private transient DOMImplementation domImpl;

	/**
	 * @see SGMLDOMImpl#createDocument(java.lang.String,java.lang.String,org.w3c.dom.DocumentType)
	 */
	public SGMLDocument() {
		this(SGMLDOMImpl.getDOMImplementation());
	}

	protected SGMLDocument(DOMImplementation imple) {
		super(null);
		this.domImpl = imple;
	}

	void check(Node node) throws DOMException {
		if (node.getOwnerDocument() != this && !(node instanceof SGMLDocType)) {
			throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, node
					+ " created from " + node.getOwnerDocument() + " this.") {
			};
		}
		switch (node.getNodeType()) {
		case ELEMENT_NODE:
			if (documentElement == null) {
				documentElement = (Element) node;
			} else {
				throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR,
						" document cannot have roots.") {
				};
			}
			break;
		case PROCESSING_INSTRUCTION_NODE:
		case COMMENT_NODE:
			break;
		case DOCUMENT_TYPE_NODE:
			doctype = (DocumentType) node;
			((SGMLNode) node).ownerDocument = this;
			break;
		default:
			throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, node
					+ " is not allowed as a child of " + this) {
			};
		}
	}

	public Node cloneNode(boolean deep) {
		SGMLDocument ret = (SGMLDocument) super.cloneNode(true);
		setOwnerDocument(ret, ret);
		for (Node child = ret.firstChild; child != null; child = child
				.getNextSibling()) {
			if (child instanceof Element) {
				ret.documentElement = (Element) child;
			} else if (child instanceof DocumentType) {
				ret.doctype = (DocumentType) child;
			}
		}
		return ret;
	}

	private void setOwnerDocument(SGMLNode ret, Document doc) {
		ret.ownerDocument = doc;
		for (SGMLNode child = (SGMLNode) ret.getFirstChild(); child != null; child = (SGMLNode) child
				.getNextSibling()) {
			setOwnerDocument(child, doc);
		}
	}

	public Attr createAttribute(String name) {
		return new SGMLAttribute(name, name, this);
	}

	public CDATASection createCDATASection(String c) {
		return new SGMLCDATASection(c, this);
	}

	public Comment createComment(String data) {
		return new SGMLComment(data, this);
	}

	public DocumentFragment createDocumentFragment() {
		return new SGMLDocumentFragment(this);
	}

	public Element createElement(String tagName) {
		return new SGMLElement(tagName, this);
	}

	public EntityReference createEntityReference(String a) throws DOMException {
		throw new DOMException(DOMException.NOT_SUPPORTED_ERR,
				"cannot create Entity Ref.") {
		};
	}

	public ProcessingInstruction createProcessingInstruction(String target,
			String data) {
		return new SGMLPI(target, data, this);
	}

	public Text createTextNode(String data) {
		return new SGMLText(data, this);
	}

	public DocumentType getDoctype() {
		return doctype;
	}

	public Element getDocumentElement() {
		return documentElement;
	}

	// implementation of Document interface;
	public Node getDocumentType() {
		return doctype;
	}

	public NodeList getElementsByTagName(String tagname) {
		final boolean all = tagname.equals("*");
		final String targetName = tagname;
		return new NodeList() {
			public int getLength() {
				int ret = 0;
				Node tmp1, tmp2;
				tmp1 = documentElement;
				outer: while (tmp1 != null) {
					if (tmp1 instanceof Element
							&& (all || targetName.equalsIgnoreCase(tmp1
									.getNodeName()))) {
						ret++;
					}
					if ((tmp2 = tmp1.getFirstChild()) == null) {
						if (tmp1 == documentElement) {
							break outer;
						} else {
							tmp2 = tmp1.getNextSibling();
						}
					}
					while (tmp2 == null && tmp1 != null) {
						tmp1 = tmp2 = tmp1.getParentNode();
						if (tmp1 != documentElement) {
							tmp2 = tmp1.getNextSibling();
						} else {
							break outer;
						}
					}
					tmp1 = tmp2;
				}
				return ret;
			}

			public Node item(int index) {
				Node tmp1, tmp2;
				tmp1 = documentElement;
				outer: while (tmp1 != null) {
					if (tmp1 instanceof Element
							&& (all || targetName.equalsIgnoreCase(tmp1
									.getNodeName()))) {
						if (index == 0) {
							return tmp1;
						} else {
							index--;
						}
					}
					if ((tmp2 = tmp1.getFirstChild()) == null) {
						if (tmp1 == documentElement) {
							break outer;
						} else {
							tmp2 = tmp1.getNextSibling();
						}
					}
					while (tmp2 == null && tmp1 != null) {
						tmp1 = tmp2 = tmp1.getParentNode();
						if (tmp1 != documentElement) {
							tmp2 = tmp1.getNextSibling();
						} else {
							break outer;
						}
					}
					tmp1 = tmp2;
				}
				return null;
			}
		};
	}

	public DOMImplementation getImplementation() {
		return this.domImpl;
	}

	public Node getNextSibling() {
		return null;
	}

	public String getNodeName() {
		return "#document";
	}

	// implementation of Node interface
	public short getNodeType() {
		return DOCUMENT_NODE;
	}

	public String getNodeValue() {
		return null;
	}

	public Document getOwnerDocument() {
		return null;
	}

	public Node getParentNode() {
		return null;
	}

	/**
	 * A Document object is the root node. So this have no siblings.
	 */
	public Node getPreviousSibling() {
		return null;
	}

	/**
	 * This method was created in VisualAge.
	 * 
	 * @return org.w3c.dom.Node
	 * @param oldChild
	 *            org.w3c.dom.Node
	 * @exception org.w3c.dom.DOMException
	 *                The exception description.
	 */
	public Node removeChild(Node oldChild) throws DOMException {
		if (oldChild == documentElement) {
			documentElement = null;
		} else if (oldChild == doctype) {
			doctype = null;
		}
		return super.removeChild(oldChild);
	}

	public void setNodeValue(String nodeValue) throws DOMException {
		throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR,
				"#document is always null") {
		};
	}

	public void printAsXML(String publicID, URL location, PrintWriter pw,
			boolean indent) throws IOException {
		printAsXML(publicID, location, pw, indent, null);
	}

	/**
	 * Print Document as XML
	 * 
	 * @param public
	 *            ID
	 * @param DTD's
	 *            location
	 * @param pw
	 *            stream to write this document.
	 * @param indent
	 *            indent if true. Otherwise, not indent.
	 * @param enc
	 */
	public void printAsXML(String publicID, URL location, PrintWriter pw,
			boolean indent, String enc) throws IOException {
		if (enc == null) {
			pw.println("<?xml version=\"1.0\"?>");
		} else {
			pw.println("<?xml version=\"1.0\" encoding=\"" + enc + "\"?>");
		}
		if (publicID != null) {
			pw.print("<!DOCTYPE " + documentElement.getTagName() + " PUBLIC \""
					+ publicID + '"');
			if (location != null) {
				pw.println(" \"" + location + "\">");
			} else {
				pw.println('>');
			}
		}
		((SGMLElement) documentElement).printAsXML(pw, 0, indent);
		pw.println();
		pw.flush();
		// charEntities4Xml = null;
	}

	public void printAsXML(PrintWriter pw, boolean indent, String enc)
			throws IOException {
		printAsXML(null, null, pw, indent, enc);
	}

	/**
	 * Print Document as SGML. starttag's string in this document are from the
	 * original document (see {@link SGMLElement#toString()}. Even if
	 * attributes in elements are modified, starttag's string does not change.
	 * 
	 * @param DTD's
	 *            location
	 * @param pw
	 *            stream to write this document.
	 */
	public void printAsSGML(PrintWriter pw, boolean indent) throws IOException {
		if (doctype != null) {
			pw.println(doctype.toString());
		}
		if (documentElement != null)
			((SGMLElement) documentElement).printAsSGML(pw, 0, indent);
		pw.println();
		pw.flush();
	}

	/**
	 * @serial
	 */
	private Hashtable charEntities4Xml;

	String getEntityOrigin4Xml(String entity) {
		return (String) charEntities4Xml.get(entity);
	}

	private transient SGMLDocTypeDef dtd;

	public SGMLDocTypeDef getDTD() {
		return dtd;
	}

	public void setDTD(SGMLDocTypeDef dtd) {
		this.dtd = dtd;
	}

	String getEntityOrigin(Character Ch) {
		return (String) charNumEntities.get(Ch);
	}

	/**
	 * @serial
	 */
	private Hashtable<Character, String> charNumEntities = new Hashtable<Character, String>();

	void putCharNumEntity(Character C, String ent) {
		charNumEntities.put(C, ent);
	}

	String getCharNumEntity(Character C) {
		return (String) charNumEntities.get(C);
	}

	// DOM Level 2

	public Node importNode(Node importedNode, boolean deep) throws DOMException {
		Node ret;
		switch (importedNode.getNodeType()) {
		case Node.ELEMENT_NODE:
			ret = createElement(importedNode.getNodeName());
			NamedNodeMap attributes = importedNode.getAttributes();
			for (int i = 0; i < attributes.getLength(); i++) {
				Attr importedAttr = (Attr) attributes.item(i);
				if (importedAttr.getSpecified()) {
					Attr attr = createAttribute(importedAttr.getNodeName());
					attr.setValue(importedAttr.getValue());
					((Element) ret).setAttributeNode(attr);
				}
			}
			break;
		case Node.ATTRIBUTE_NODE:
			ret = createAttribute(importedNode.getNodeName());
			((Attr) ret).setValue(importedNode.getNodeValue());
			break;
		case Node.TEXT_NODE:
			ret = createTextNode(importedNode.getNodeValue());
			break;
		case Node.CDATA_SECTION_NODE:
			ret = createCDATASection(importedNode.getNodeValue());
			break;
		case Node.COMMENT_NODE:
			ret = createComment(importedNode.getNodeValue());
			break;
		case Node.PROCESSING_INSTRUCTION_NODE:
			ProcessingInstruction pi = (ProcessingInstruction) importedNode;
			ret = createProcessingInstruction(pi.getTarget(), pi.getData());
			break;
		case Node.ENTITY_REFERENCE_NODE:
			throw new DOMException(DOMException.NOT_SUPPORTED_ERR,
					"ENTITY_REFERENCE: " + importedNode) {
			};
		case Node.ENTITY_NODE:
			throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "ENTITY: "
					+ importedNode) {
			};
		case Node.DOCUMENT_NODE:
			throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "DOCUMENT: "
					+ importedNode) {
			};
		case Node.DOCUMENT_TYPE_NODE:
			throw new DOMException(DOMException.NOT_SUPPORTED_ERR,
					"DOCUMENT_TYPE: " + importedNode) {
			};
		case Node.DOCUMENT_FRAGMENT_NODE:
			ret = createDocumentFragment();
			break;
		case Node.NOTATION_NODE:
			throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "NOTATION: "
					+ importedNode) {
			};
		default:
			throw new DOMException(DOMException.NOT_SUPPORTED_ERR,
					"Unknown node type: " + importedNode.getNodeType()) {
			};
		}
		if (deep) {
			for (Node importedChild = importedNode.getFirstChild(); importedChild != null; importedChild = importedChild
					.getNextSibling()) {
				ret.appendChild(importNode(importedChild, true));
			}
		}
		return ret;
	}

	/**
	 * @param namespaceURI
	 *            always ignored.
	 * @return same as <code>createElement(qualifiedName)</code>
	 */
	public Element createElementNS(String namespaceURI, String qualifiedName)
			throws DOMException {
		return createElement(qualifiedName);
	}

	/**
	 * @param namespaceURI
	 *            always ignored.
	 * @return same as <code>createAttribute(qualifiedName)</code>
	 */
	public Attr createAttributeNS(String namespaceURI, String qualifiedName)
			throws DOMException {
		return createAttribute(qualifiedName);
	}

	/**
	 * @param namespaceURI
	 *            always ignored.
	 * @return same as <code>getElementsByTagName(localName)</code>
	 */
	public NodeList getElementsByTagNameNS(String namespaceURI, String localName) {
		return getElementsByTagName(localName);
	}

	/**
	 * Returns the <code>Element</code> whose <code>ID</code> is given by
	 * <code>elementId</code>. If more than one element has this
	 * <code>ID</code> The first element in the depth-first and pre-order
	 * traversal is returned.
	 */
	public Element getElementById(String elementID) {
		return getElementById(documentElement, elementID);
	}

	private Element getElementById(Element el, String elementID) {
		if (el.getAttribute("id").equals(elementID)) {
			return el;
		} else {
			for (Node child = el.getFirstChild(); child != null; child = child
					.getNextSibling()) {
				if (child instanceof Element) {
					Element ret = getElementById((Element) child, elementID);
					if (ret != null) {
						return ret;
					}
				}
			}
			return null;
		}
	}

	/**
	 * DOM Level 3
	 */

	public Node adoptNode(Node source) throws DOMException {
		// TODO Auto-generated method stub
		return null;
	}

	public String getDocumentURI() {
		// TODO Auto-generated method stub
		return null;
	}

	public DOMConfiguration getDomConfig() {
		// TODO Auto-generated method stub
		return null;
	}

	public String getInputEncoding() {
		// TODO Auto-generated method stub
		return null;
	}

	public boolean getStrictErrorChecking() {
		// TODO Auto-generated method stub
		return false;
	}

	public String getXmlEncoding() {
		// TODO Auto-generated method stub
		return null;
	}

	public boolean getXmlStandalone() {
		// TODO Auto-generated method stub
		return false;
	}

	public String getXmlVersion() {
		// TODO Auto-generated method stub
		return null;
	}

	public void normalizeDocument() {
		// TODO Auto-generated method stub

	}

	public Node renameNode(Node n, String namespaceURI, String qualifiedName)
			throws DOMException {
		// TODO Auto-generated method stub
		return null;
	}

	public void setDocumentURI(String documentURI) {
		// TODO Auto-generated method stub

	}

	public void setStrictErrorChecking(boolean strictErrorChecking) {
		// TODO Auto-generated method stub

	}

	public void setXmlStandalone(boolean xmlStandalone) throws DOMException {
		// TODO Auto-generated method stub

	}

	public void setXmlVersion(String xmlVersion) throws DOMException {
		// TODO Auto-generated method stub

	}
}