/*******************************************************************************
 * 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.dtd.core.internal;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.swt.graphics.Image;
import org.eclipse.wst.dtd.core.internal.document.DTDModelImpl;
import org.eclipse.wst.dtd.core.internal.event.IDTDFileListener;
import org.eclipse.wst.dtd.core.internal.event.NodesEvent;
import org.eclipse.wst.dtd.core.internal.parser.DTDRegionTypes;
import org.eclipse.wst.dtd.core.internal.util.DTDExternalReferenceRemover;
import org.eclipse.wst.dtd.core.internal.util.DTDModelUpdater;
import org.eclipse.wst.dtd.core.internal.util.DTDNotationReferenceRemover;
import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
import org.eclipse.wst.sse.core.internal.provisional.events.NewDocumentEvent;
import org.eclipse.wst.sse.core.internal.provisional.events.RegionChangedEvent;
import org.eclipse.wst.sse.core.internal.provisional.events.RegionsReplacedEvent;
import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentRegionsReplacedEvent;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegionList;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;

public class DTDFile implements IndexedRegion {
	 private NodeList attlistList = new NodeList(this, DTDRegionTypes.ATTLIST_TAG);
	private NodeList commentList = new NodeList(this, DTDRegionTypes.COMMENT_START);

	boolean creatingNewModel = false;
	private DTDModelImpl fDTDModel;

	private NodeList elementList = new NodeList(this, DTDRegionTypes.ELEMENT_TAG);
	private NodeList entityList = new NodeList(this, DTDRegionTypes.ENTITY_TAG);

	private List folderList = null;

	private boolean isMovingNode = false;

	private List modelListeners = new ArrayList();

	private List nodeList = new ArrayList();
	private NodeList notationList = new NodeList(this, DTDRegionTypes.NOTATION_TAG);
	private NodeList unrecognizedList = new NodeList(this, DTDRegionTypes.UNKNOWN_CONTENT);

	public DTDFile(DTDModelImpl dtdModel) {
		this.fDTDModel = dtdModel;
	}

	public void addDTDFileListener(IDTDFileListener listener) {
		modelListeners.add(listener);
	}

	protected void addNode(DTDNode node) {
		addNode(nodeList.size(), node);
	}

	protected void addNode(int index, DTDNode node) {
		nodeList.add(index, node);
		/*
		 * if (index < nodeList.size()) { insertBefore(node, (DTDNode)
		 * nodeList.get(index)); } else { appendChild(node); }
		 */
	}

	public DTDNode buildNode(IStructuredDocumentRegion flatNode) {
		// ITextRegionList regions = flatNode.getRegions();
		DTDNode node = null;
		if (isElement(flatNode)) {
			// then this is an element
			node = new Element(this, flatNode);
		}
		else if (isEntity(flatNode)) {
			node = new Entity(this, flatNode);
		}
		else if (isNotation(flatNode)) {
			node = new Notation(this, flatNode);
		}
		else if (isAttributeList(flatNode)) {
			node = new AttributeList(this, flatNode);
		}
		else if (isComment(flatNode)) {
			node = new Comment(this, flatNode);
		}
		else if (isParameterEntityReference(flatNode)) {
			node = new ParameterEntityReference(this, flatNode);
		}
		else if (!flatNode.getText().trim().equals("")) { //$NON-NLS-1$
			node = new Unrecognized(this, flatNode);
		}
		if (node != null) {
			insertNode(node);
			node.resolveRegions();
		}
		return node;
	}

	public void buildNodes(IStructuredDocumentRegionList list) {
		NodesEvent addedDTDNodes = new NodesEvent();

		TopLevelNode previousNode = null;
		for (int i = 0; i < list.getLength(); i++) {
			IStructuredDocumentRegion flatNode = list.item(i);
			TopLevelNode node = (TopLevelNode) buildNode(flatNode);
			// if we don't create a node, then we assume that the flat
			// node was whitespace. Tack it on to a previous toplevel
			// node
			if (node != null) {
				previousNode = node;
				addedDTDNodes.add(node);
			}
			else {
				if (previousNode != null) {
					previousNode.addWhitespaceStructuredDocumentRegion(flatNode);
				}
			}
		}

		if (addedDTDNodes.getNodes().size() > 0)// &&
		// creatingNewModel == false)
		{
			// now tell people about the additions
			notifyNodesAdded(addedDTDNodes);
		}
	}

	// Implements IndexedRegion

	public boolean contains(int testPosition) {
		return getStartOffset() <= testPosition && testPosition <= getEndOffset();
	}

	public void createAttributeList(DTDNode node, String name, boolean isAfter) {
		getDTDModel().beginRecording(this, DTDCoreMessages._UI_LABEL_DTD_FILE_ADD_ATTR_LIST); //$NON-NLS-1$
		String newStream = "<!ATTLIST " + name + ">\n"; //$NON-NLS-1$ //$NON-NLS-2$
		int offset = getInsertOffset(node, isAfter);
		getStructuredDocument().replaceText(this, offset, 0, newStream);
		getDTDModel().endRecording(this);
	}

	public void createComment(DTDNode node, String name, boolean isAfter) {
		getDTDModel().beginRecording(this, DTDCoreMessages._UI_LABEL_DTD_FILE_ADD_COMMENT); //$NON-NLS-1$
		String newStream = "<!-- " + name + " -->\n"; //$NON-NLS-1$ //$NON-NLS-2$
		int offset = getInsertOffset(node, isAfter);
		getStructuredDocument().replaceText(this, offset, 0, newStream);
		getDTDModel().endRecording(this);
	}

	public void createElement(DTDNode node, String name, boolean isAfter) {
		getDTDModel().beginRecording(this, DTDCoreMessages._UI_LABEL_DTD_FILE_ADD_ELEMENT); //$NON-NLS-1$
		String newStream = "<!ELEMENT " + name + " EMPTY>\n"; //$NON-NLS-1$ //$NON-NLS-2$
		int offset = getInsertOffset(node, isAfter);
		getStructuredDocument().replaceText(this, offset, 0, newStream);
		getDTDModel().endRecording(this);
	}

	public void createEntity(DTDNode node, String name, boolean isAfter) {
		getDTDModel().beginRecording(this, DTDCoreMessages._UI_LABEL_DTD_FILE_ADD_ENTITY); //$NON-NLS-1$
		String newStream = "<!ENTITY " + name + " \"\">\n"; //$NON-NLS-1$//$NON-NLS-2$
		int offset = getInsertOffset(node, isAfter);
		getStructuredDocument().replaceText(this, offset, 0, newStream);
		getDTDModel().endRecording(this);
	}

	public void createNotation(DTDNode node, String name, boolean isAfter) {
		getDTDModel().beginRecording(this, DTDCoreMessages._UI_LABEL_DTD_FILE_ADD_NOTATION); //$NON-NLS-1$
		String newStream = "<!NOTATION " + name + " SYSTEM \"\">\n"; //$NON-NLS-1$ //$NON-NLS-2$
		int offset = getInsertOffset(node, isAfter);
		getStructuredDocument().replaceText(this, offset, 0, newStream);
		getDTDModel().endRecording(this);
	}

	public void createParameterEntityReference(DTDNode node, String name, boolean isAfter) {
		getDTDModel().beginRecording(this, DTDCoreMessages._UI_LABEL_DTD_FILE_ADD_PARM_ENTITY_REF); //$NON-NLS-1$
		String newStream = name + "\n"; //$NON-NLS-1$
		int offset = getInsertOffset(node, isAfter);
		getStructuredDocument().replaceText(this, offset, 0, newStream);
		getDTDModel().endRecording(this);
	}

	public void deleteNode(DTDNode node) {
		getDTDModel().beginRecording(this, DTDCoreMessages._UI_LABEL_DTD_FILE_DELETE); //$NON-NLS-1$
		deleteNode(this, node);
		getDTDModel().endRecording(this);
	}

	public void deleteNode(Object requestor, DTDNode node) {
		DTDNode parent = (DTDNode) node.getParentNode();
		if (parent != null) {
			parent.delete(requestor, node);
		}
		else {
			if (!isMovingNode) {
				DTDModelUpdater updater = new DTDModelUpdater();
				updater.objectAboutToBeDeleted(requestor, node);
				if (node instanceof ParameterEntityReference) {
					Entity referencedEntity = ((ParameterEntityReference) node).getEntityObject();
					if (referencedEntity != null) {
						// remove references to all elements and parm entities
						// contained in our current model
						DTDExternalReferenceRemover remover = new DTDExternalReferenceRemover();
						remover.externalReferenceAboutToChange(requestor, referencedEntity);
					}
				}
				else if (node instanceof Notation) {
					Notation notation = ((Notation) node);
					DTDNotationReferenceRemover remover = new DTDNotationReferenceRemover();
					remover.notationAboutToBeDeleted(requestor, notation);
				}
			}

			// no parent? then delete up until the start of the next node
			// if it is a top level node
			int startOffset = node.getStartOffset();
			int endOffset = node.getWhitespaceEndOffset();
			if (node instanceof TopLevelNode) {
				endOffset = getInsertOffset(node, true);
			}
			getStructuredDocument().replaceText(requestor, startOffset, endOffset - startOffset, ""); //$NON-NLS-1$
		}
	}

	public NodeList getComments() {
		return commentList;
	}

	public DTDModelImpl getDTDModel() {
		return fDTDModel;
	}

	public NodeList getElementsAndParameterEntityReferences() {
		return elementList;
	}

	public int getEndOffset() {
		int result = -1;
		IStructuredDocumentRegion region = getStructuredDocument().getLastStructuredDocumentRegion();
		if (region != null) {
			result = region.getEndOffset();
		}
		return result;
	}

	public int getLength() {
		int result = -1;
		int start = getStartOffset();
		if (start >= 0) {
			int end = getEndOffset();
			if (end >= 0) {
				result = end - start;
				if (result < -1) {
					result = -1;
				}
			}
		}
		return result;
	}

	public NodeList getEntities() {
		return entityList;
	}

	public Image getImage() {
		return DTDCorePlugin.getInstance().getImage(DTDResource.DTDFILEICON);
	}



	public int getInsertOffset(DTDNode node, boolean isAfter) {
		int offset = 0;
		if (node != null) {
			if (isAfter) {
				// then get the next node and use it's start offset
				int index = getNodes().indexOf(getNode(node.getStructuredDTDDocumentRegion()));

				DTDNode afterNode = null;
				if (index + 1 < getNodes().size()) {
					afterNode = (DTDNode) getNodes().get(index + 1);
				}
				if (afterNode != null) {
					offset = afterNode.getStructuredDTDDocumentRegion().getStartOffset();
				}
				else {
					// add to end
					if (getStructuredDocument().getLastStructuredDocumentRegion() != null) {
						offset = getStructuredDocument().getLastStructuredDocumentRegion().getEndOffset();
					}
				}
			}
			else {
				offset = node.getStructuredDTDDocumentRegion().getStartOffset();
			}
		}
		else {
			// add to end
			if (getStructuredDocument().getLastStructuredDocumentRegion() != null) {
				offset = getStructuredDocument().getLastStructuredDocumentRegion().getEndOffset();
			}
		}
		return offset;
	}

	public String getName() {
		org.eclipse.core.runtime.Path path = new org.eclipse.core.runtime.Path(getDTDModel().getId().toString());
		return path.lastSegment();
	}

	public DTDNode getNode(IStructuredDocumentRegion flatNode) {
		for (int i = 0; i < nodeList.size(); i++) {
			DTDNode node = (DTDNode) nodeList.get(i);
			if (node.getStructuredDTDDocumentRegion() == flatNode) {
				return node;
			}
		}
		return null;
	}

	public IndexedRegion getNodeAt(int offset) {
		DTDNode node = getTopLevelNodeAt(offset);
		if (node != null) {
			return node.getDeepestNode(offset);
		}
		return null;
	}

	public IndexedRegion getNodeAt(int startOffset, int endOffset) {
		DTDNode node = getTopLevelNodeAt(startOffset);
		if (node != null) {
			return node.getDeepestNode(startOffset, endOffset);
		}
		return null;
	}

	public List getNodeLists() {
		if (folderList == null) {
			folderList = new ArrayList();
			folderList.add(notationList);
			folderList.add(entityList);
			folderList.add(elementList);
			folderList.add(attlistList);
			folderList.add(commentList);
			folderList.add(unrecognizedList);
		}
		return folderList;
	}

	public List getNodes() {
		return nodeList;
	}

	public NodeList getNotations() {
		return notationList;
	}

	public int getStartOffset() {
		int result = -1;
		IStructuredDocumentRegion region = getStructuredDocument().getFirstStructuredDocumentRegion();
		if (region != null) {
			result = region.getStartOffset();
		}
		return result;
	}

	public IStructuredDocument getStructuredDocument() {
		return fDTDModel.getStructuredDocument();
	}

	public DTDNode getTopLevelNodeAt(int offset) {
		for (int i = 0; i < nodeList.size(); i++) {
			DTDNode node = (DTDNode) nodeList.get(i);
			if (node.contains(offset)) {
				return node;
			}
		}
		return null;
	}

	public NodeList getUnrecognized() {
		return unrecognizedList;
	}

	public void insertIntoModel(Object requestor, DTDNode reference, DTDNode node, boolean isAfter) {
		String nodeText = ""; //$NON-NLS-1$
		if (node instanceof TopLevelNode) {
			nodeText = ((TopLevelNode) node).getFullText();
		}
		else {
			nodeText = node.getNodeText();
		}
		int offset = getInsertOffset(reference, isAfter);
		getStructuredDocument().replaceText(requestor, offset, 0, nodeText);
	}


	public void insertNode(DTDNode node) {
		int startOffset = node.getStartOffset();
		int insertIndex = -1;
		// System.out.println("startoffset = " + startOffset);
		for (int i = 0; i < getNodes().size(); i++) {
			DTDNode currentNode = (DTDNode) getNodes().get(i);
			// System.out.println("currentNode endOffset = "
			// +currentNode.getEndOffset());

			if (currentNode.getEndOffset() > startOffset) {
				// System.out.println("endoffset " +
				// currentNode.getEndOffset() + " > " + startOffset);
				insertIndex = i;
				break;
			}
		}
		if (insertIndex == -1) {
			insertIndex = getNodes().size();
		}


		// System.out.println("insert index = " + insertIndex);

		addNode(insertIndex, node);
	}

	// it is assumed that flatnode contains at least 3 regions
	public boolean isAttributeList(IStructuredDocumentRegion flatNode) {
		if (flatNode.getRegions().size() >= 3) {
			ITextRegion second = flatNode.getRegions().get(1);
			ITextRegion third = flatNode.getRegions().get(2);
			if (second.getType().equals(DTDRegionTypes.EXCLAMATION) && third.getType().equals(DTDRegionTypes.ATTLIST_TAG)) {
				return true;
			}
		}
		return false;
	}

	// it is assumed that flatnode contains at least 3 regions
	public boolean isComment(IStructuredDocumentRegion flatNode) {
		if (flatNode.getRegions().size() >= 2) {
			ITextRegion region = flatNode.getRegions().get(1);
			if (region.getType().equals(DTDRegionTypes.COMMENT_START)) {
				return true;
			}
		}
		return false;
	}

	// it is assumed that flatnode contains at least 3 regions
	public boolean isElement(IStructuredDocumentRegion flatNode) {
		if (flatNode.getRegions().size() >= 3) {
			ITextRegion second = flatNode.getRegions().get(1);
			ITextRegion third = flatNode.getRegions().get(2);
			if (second.getType().equals(DTDRegionTypes.EXCLAMATION) && third.getType().equals(DTDRegionTypes.ELEMENT_TAG)) {
				return true;
			}
		}
		return false;
	}

	// it is assumed that flatnode contains at least 3 regions
	public boolean isEntity(IStructuredDocumentRegion flatNode) {
		if (flatNode.getRegions().size() >= 3) {
			ITextRegion second = flatNode.getRegions().get(1);
			ITextRegion third = flatNode.getRegions().get(2);
			if (second.getType().equals(DTDRegionTypes.EXCLAMATION) && third.getType().equals(DTDRegionTypes.ENTITY_TAG)) {
				return true;
			}
		}
		return false;
	}

	// it is assumed that flatnode contains at least 3 regions
	public boolean isNotation(IStructuredDocumentRegion flatNode) {
		if (flatNode.getRegions().size() >= 3) {
			ITextRegion second = flatNode.getRegions().get(1);
			ITextRegion third = flatNode.getRegions().get(2);
			if (second.getType().equals(DTDRegionTypes.EXCLAMATION) && third.getType().equals(DTDRegionTypes.NOTATION_TAG)) {
				return true;
			}
		}
		return false;
	}

	// it is assumed that flatnode contains at least 3 regions
	public boolean isParameterEntityReference(IStructuredDocumentRegion flatNode) {
		if (flatNode.getRegions().size() == 1) {
			ITextRegion region = flatNode.getRegions().get(0);
			if (region.getType().equals(DTDRegionTypes.ENTITY_PARM)) {
				return true;
			}
		}
		return false;
	}

	boolean isSameTopLevelType(DTDNode affectedNode) {
		IStructuredDocumentRegion flatNode = affectedNode.getStructuredDTDDocumentRegion();
		// return true if the flatnode still matches what the affectedNode
		// is representing
		if (affectedNode instanceof Element && isElement(flatNode)) {
			return true;
		}
		if (affectedNode instanceof Entity && isEntity(flatNode)) {
			return true;
		}
		if (affectedNode instanceof Comment && isComment(flatNode)) {
			return true;
		}
		if (affectedNode instanceof AttributeList && isAttributeList(flatNode)) {
			return true;
		}
		if (affectedNode instanceof Notation && isNotation(flatNode)) {
			return true;
		}
		if (affectedNode instanceof Unrecognized && isUnrecognized(flatNode)) {
			return true;
		}
		return false;
	}

	public boolean isUnrecognized(IStructuredDocumentRegion flatNode) {
		return !isElement(flatNode) && !isEntity(flatNode) && !isNotation(flatNode) && !isParameterEntityReference(flatNode) && !isAttributeList(flatNode) && !isComment(flatNode);
	}

	public void moveNode(Object requestor, DTDNode referenceNode, DTDNode nodeToMove, boolean isAfter) {
		isMovingNode = true;

		deleteNode(requestor, nodeToMove);
		insertIntoModel(requestor, referenceNode, nodeToMove, isAfter);
		isMovingNode = false;
	}

	public void newModel(NewDocumentEvent event) {
		creatingNewModel = true;
		nodeList.clear();
		NodesEvent removeEvent = new NodesEvent();
		removeEvent.getNodes().addAll(nodeList);
		notifyNodesRemoved(removeEvent);
		/* removeChildNodes(); */

		if (event.getStructuredDocument() != null && event.getStructuredDocument().getRegionList() != null) {
			buildNodes(event.getStructuredDocument().getRegionList());
		}
		creatingNewModel = false;
	}

	public void nodesReplaced(StructuredDocumentRegionsReplacedEvent event) {
		IStructuredDocumentRegionList oldNodes = event.getOldStructuredDocumentRegions();
		NodesEvent removedDTDNodes = new NodesEvent();
		for (int i = 0; i < oldNodes.getLength(); i++) {
			IStructuredDocumentRegion flatNode = oldNodes.item(i);

			for (Iterator iter = getNodes().iterator(); iter.hasNext();) {
				DTDNode node = (DTDNode) iter.next();
				if (node.getStructuredDTDDocumentRegion() == flatNode) {
					removedDTDNodes.add(node);
				}
			}
		}

		buildNodes(event.getNewStructuredDocumentRegions());

		if (removedDTDNodes.getNodes().size() > 0) {
			notifyNodesRemoved(removedDTDNodes);
			removeNodes(removedDTDNodes.getNodes());
		}
	}

	public void notifyNodeChanged(DTDNode node) {
		Iterator iter = modelListeners.iterator();
		while (iter.hasNext()) {
			IDTDFileListener listener = (IDTDFileListener) iter.next();
			listener.nodeChanged(node);
		}
	}

	public void notifyNodesAdded(NodesEvent addedNodes) {
		Iterator iter = modelListeners.iterator();
		while (iter.hasNext()) {
			IDTDFileListener listener = (IDTDFileListener) iter.next();
			listener.nodesAdded(addedNodes);
		}
	}

	protected void notifyNodesRemoved(NodesEvent event) {
		Iterator iter = modelListeners.iterator();
		while (iter.hasNext()) {
			IDTDFileListener listener = (IDTDFileListener) iter.next();
			listener.nodesRemoved(event);
		}
	}

	public void rebuildNodes(List nodes) {
		// remove the old nodes
		removeNodes(nodes);

		// now rebuild them
		NodesEvent addedDTDNodes = new NodesEvent();
		Iterator dtdNodes = nodes.iterator();
		while (dtdNodes.hasNext()) {
			DTDNode dtdNode = (DTDNode) dtdNodes.next();
			// System.out.println("rebuilding " +
			// dtdNode.getStructuredDocumentRegion().getText());

			DTDNode node = buildNode(dtdNode.getStructuredDTDDocumentRegion());
			if (node != null) {
				addedDTDNodes.add(node);
			}
		}
		if (addedDTDNodes.getNodes().size() > 0) {
			// now tell people about the additions
			notifyNodesAdded(addedDTDNodes);
		}
	}

	public void regionChanged(RegionChangedEvent event) {
		ITextRegion changedRegion = event.getRegion();
		IStructuredDocumentRegion flatNode = event.getStructuredDocumentRegion();
		DTDNode affectedNode = (DTDNode) getNodeAt(flatNode.getStartOffset(changedRegion), flatNode.getEndOffset(changedRegion));
		if (affectedNode != null) {
			// no need to resolve regions as it is just a change
			// affectedNode.resolveRegions();
			notifyNodeChanged(affectedNode);
		}
	}

	public void regionsReplaced(RegionsReplacedEvent event) {
		List nodesToRebuild = new ArrayList();
		IStructuredDocumentRegion flatNode = event.getStructuredDocumentRegion();
		DTDNode affectedNode = getNode(flatNode);

		if (!isSameTopLevelType(affectedNode)) {
			nodesToRebuild.add(affectedNode);
			rebuildNodes(nodesToRebuild);
		}
		else {
			affectedNode.resolveRegions();
			notifyNodeChanged(affectedNode);
			// now try and determine which ones were added
			NodesEvent addedDTDNodes = new NodesEvent();
			ITextRegionList newRegions = event.getNewRegions();
			int size = newRegions.size();
			for (int i = 0; i < size; i++) {
				ITextRegion region = newRegions.get(i);
				DTDNode deepestNode = affectedNode.getDeepestNode(flatNode.getStartOffset(region), flatNode.getEndOffset(region));
				if (!addedDTDNodes.getNodes().contains(deepestNode)) {
					addedDTDNodes.add(deepestNode);
				}
			}
			if (addedDTDNodes.getNodes().size() > 0) {
				notifyNodesAdded(addedDTDNodes);
			}
		}
	}

	public void removeDTDFileListener(IDTDFileListener listener) {
		modelListeners.remove(listener);
	}

	protected void removeNodes(List nodes) {
		getNodes().removeAll(nodes);
		/*
		 * for (int i = 0; i < nodes.size(); i++) {
		 * removeChild((DTDNode)nodes.get(i)); } // end of for ()
		 */
	}
}
