/*******************************************************************************
 * 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.List;

import org.eclipse.swt.graphics.Image;
import org.eclipse.wst.dtd.core.internal.parser.DTDRegionTypes;
import org.eclipse.wst.dtd.core.internal.text.RegionIterator;
import org.eclipse.wst.dtd.core.internal.util.DTDUniqueNameHelper;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;


public class CMGroupNode extends CMRepeatableNode {

	public static final char CHOICE = '|';
	public static final char SEQUENCE = ',';

	protected char connector = SEQUENCE;

	// protected ArrayList children = new ArrayList();

	public CMGroupNode(DTDFile file, IStructuredDocumentRegion flatNode) {
		super(file, flatNode);
	}

	public void addChild() {
		beginRecording(this, DTDCoreMessages._UI_LABEL_CM_GRP_NODE_ADD_CHILD); //$NON-NLS-1$
		DTDNode lastNode = (DTDNode) getLastChild();
		String elementName = DTDUniqueNameHelper.getUniqueName(getChildrenList(), "ChildNode"); //$NON-NLS-1$
		if (lastNode != null) {
			replaceText(this, lastNode.getEndOffset(), 0, String.valueOf(getConnector()) + elementName); //$NON-NLS-1$
		}
		else {
			replaceText(this, getStartOffset() + 1, 0, elementName); //$NON-NLS-1$
		}

		endRecording(this);
	}

	public void addGroup() {
		beginRecording(this, DTDCoreMessages._UI_LABEL_CM_GRP_NODE_ADD_GRP); //$NON-NLS-1$
		DTDNode lastNode = (DTDNode) getLastChild();
		if (lastNode != null) {
			replaceText(this, lastNode.getEndOffset(), 0, String.valueOf(getConnector()) + " ()"); //$NON-NLS-1$
		}
		else {
			replaceText(this, getStartOffset() + 1, 0, "()"); //$NON-NLS-1$
		}

		endRecording(this);
	}

	public void delete(Object requestor, DTDNode child) {
		Object[] children = getChildren();

		if (children.length == 1 && getFirstChild() == child) {
			replaceText(requestor, child.getStartOffset(), child.getNodeLength(), null);
			return;
		}

		for (int i = 0; i < children.length - 1; i++) {
			DTDNode childA = (DTDNode) children[i];
			DTDNode childB = (DTDNode) children[i + 1];

			boolean childADeleted = childA == child;
			boolean childBDeleted = childB == child;
			if (childADeleted || childBDeleted) {
				// we found the child
				int startOffset = childADeleted ? childA.getStartOffset() : childA.getEndOffset();
				int endOffset = childADeleted ? childB.getStartOffset() : childB.getEndOffset();
				replaceText(requestor, startOffset, endOffset - startOffset, ""); //$NON-NLS-1$
				removeChild(child);
				break;
			}
		}
	}

	/**
	 * Get the value of connector.
	 * 
	 * @return value of connector.
	 */
	public char getConnector() {
		Object[] children = getChildren();
		for (int i = 0; i < children.length - 1; i++) {
			DTDNode childA = (DTDNode) children[i];
			DTDNode childB = (DTDNode) children[i + 1];

			// create a stream between the two siblings and walk it
			// note that this stream includes the last region of the first
			// sibling and the first region of the next sibling.
			// both these should be ignored
			RegionIterator iter = new RegionIterator(getStructuredDTDDocumentRegion(), childA.getEndOffset(), childB.getStartOffset());
			// stream.setFirstRegion(childA.getLastRegion());
			// stream.setLastRegion(childB.getFirstRegion());
			// Iterator iter = stream.iterator();
			// skip the first region which is the last region of childA
			// do we need this now ?
			// iter.next();
			ITextRegion currentRegion = null;
			while (iter.hasNext() && currentRegion != childB.getStartRegion()) {
				currentRegion = iter.next();
				if (currentRegion.getType() == DTDRegionTypes.CONNECTOR) {
					connector = getStructuredDTDDocumentRegion().getText(currentRegion).charAt(0);
					return connector;
				}
			}
		}
		return connector;
	}

	public Image getImage() {
		DTDCorePlugin resourcePlugin = DTDCorePlugin.getInstance();
		switch (getConnector()) {
			case SEQUENCE :
				return resourcePlugin.getImage(DTDResource.ONESEQUENCEICON);
			/*
			 * switch (getOccurrence()) { case ONCE : return
			 * resourcePlugin.getImage(DTDResource.ONESEQUENCEICON); case
			 * OPTIONAL : return
			 * resourcePlugin.getImage(DTDResource.OPTIONALSEQUENCEICON); case
			 * ONE_OR_MORE : return
			 * resourcePlugin.getImage(DTDResource.ONEORMORESEQUENCEICON);
			 * case ZERO_OR_MORE : return
			 * resourcePlugin.getImage(DTDResource.ZEROORMORESEQUENCEICON); }
			 */
			case CHOICE :
				return resourcePlugin.getImage(DTDResource.ONECHOICEICON);
		/*
		 * switch (getOccurrence()) { case ONCE : return
		 * resourcePlugin.getImage(DTDResource.ONECHOICEICON); case OPTIONAL :
		 * return resourcePlugin.getImage(DTDResource.OPTIONALCHOICEICON);
		 * case ONE_OR_MORE : return
		 * resourcePlugin.getImage(DTDResource.ONEORMORECHOICEICON); case
		 * ZERO_OR_MORE : return
		 * resourcePlugin.getImage(DTDResource.ZEROORMORECHOICEICON); }
		 */
		}
		return null;
	}

	public String getName() {
		return ""; //$NON-NLS-1$
	}

	// returns the occurrenceregion, or the last region where the occurrence
	// region should appear after
	public ITextRegion getOccurrenceRegion() {
		int nesting = 0;

		// we skip past the first left paren we see since that is the
		// beginning of our own node
		RegionIterator iter = iterator();
		// we assume the first region is the '('
		iter.next();
		ITextRegion currentRegion = null;
		while (iter.hasNext() && nesting >= 0) {
			currentRegion = iter.next();
			if (currentRegion.getType() == DTDRegionTypes.LEFT_PAREN) {
				nesting++;
			}
			if (currentRegion.getType() == DTDRegionTypes.RIGHT_PAREN) {
				nesting--;
			}
		}
		if (nesting < 0) {
			// This means we have passed over the right paren that marks the
			// end of our grouping.
			// Look for an occurrence region
			while (iter.hasNext()) {
				currentRegion = iter.next();
				if (currentRegion.getType() == DTDRegionTypes.OCCUR_TYPE) {
					return currentRegion;
				}
			}
		}
		// if we're here, this means that there is no occur region. return the
		// last region
		return iter.previous();
	}

	public String getType() {
		if (isRootElementContent()) {
			if (getFirstChild() != null) {
				CMNode node = (CMNode) getFirstChild();
				if (node.getType().equals(PCDATA)) {
					return MIXED;
				}
				else {
					return CHILDREN;
				}
			}
		}
		return ""; //$NON-NLS-1$
	}

	public void insertChildNode(Object requestor, String nodeText, int position) {
		Object[] children = getChildren();

		int startOffset = 0;
		String newText = ""; //$NON-NLS-1$
		if (position < children.length) {
			DTDNode reference = (DTDNode) children[position];
			startOffset = reference.getStartOffset();
			newText = nodeText + " " + String.valueOf(getConnector()) + " "; //$NON-NLS-1$ //$NON-NLS-2$
		}
		else if (position == children.length) {
			// add to end
			DTDNode reference = (DTDNode) children[position - 1];
			startOffset = reference.getEndOffset();
			newText = " " + String.valueOf(getConnector()) + " " + nodeText; //$NON-NLS-1$ //$NON-NLS-2$
		}
		replaceText(requestor, startOffset, 0, newText);
	}

	public void insertChildNode(String nodeText, int position) {
		beginRecording(this, DTDCoreMessages._UI_LABEL_CM_GRP_NODE_INSERT_ELEMENT); //$NON-NLS-1$
		insertChildNode(this, nodeText, position);
		endRecording(this);
	}

	public void insertIntoModel(Object requestor, CMNode reference, CMNode node, boolean isAfter) {
		String nodeText = node.getNodeText();
		List children = getChildrenList();

		int index = children.indexOf(reference);
		if (index == -1) {
			// no reference node, add it to the end??
			index = children.size();
		}
		else {
			// got an index. if we want to add after, increase by 1
			index = isAfter ? index + 1 : index;
		}
		insertChildNode(requestor, nodeText, index);
	}

	public void resolveRegions() {
		int nesting = 0;
		// children.clear();
		removeChildNodes();
		DTDNode currentGroupNode = null;
		CMBasicNode currentReferenceNode = null;
		RegionIterator iter = iterator();
		// we assume the first region is the '('
		iter.next();
		while (iter.hasNext() && nesting >= 0) {
			ITextRegion currentRegion = iter.next();
			if (nesting == 0) {
				if (currentRegion.getType().equals(DTDRegionTypes.CONTENT_PCDATA)) {
					currentGroupNode = currentReferenceNode = null;
					DTDNode pcData = new CMBasicNode(getDTDFile(), getStructuredDTDDocumentRegion());
					pcData.addRegion(currentRegion);
					appendChild(pcData);
					// children.add(pcData);
				}
				else if (currentRegion.getType().equals(DTDRegionTypes.NAME)) {
					// we have hit a new reference node. Make sure we reset
					// the groupnode var so it doesn't collect more regions
					currentGroupNode = null;
					currentReferenceNode = new CMBasicNode(getDTDFile(), getStructuredDTDDocumentRegion());
					currentReferenceNode.addRegion(currentRegion);
					appendChild(currentReferenceNode);
					// children.add(currentReferenceNode);
				}
				else if (currentRegion.getType().equals(DTDRegionTypes.OCCUR_TYPE)) {
					// we could potentially flag an error here if we hit an
					// occurrence type and currentRefNode and currentGroupNode
					// are null
					if (currentReferenceNode != null) {
						// currentReferenceNode.setOccurrence(currentRegion.getText().toCharArray()[0]);
						currentReferenceNode.addRegion(currentRegion);
						currentReferenceNode = null;
					}
				}
				else if (currentRegion.getType().equals(DTDRegionTypes.CONNECTOR)) {
					// note that if connector is already set and it is
					// different from the current connector region, then we
					// have an error!
					// setConnector(currentRegion.getText().toCharArray()[0]);
				}
				else if (currentRegion.getType().equals(DTDRegionTypes.LEFT_PAREN)) {
					if (currentGroupNode == null) {
						// we have hit a new group. Make sure we reset the
						// referencenode var so it doesn't collect any more
						// regions
						currentReferenceNode = null;
						currentGroupNode = new CMGroupNode(getDTDFile(), getStructuredDTDDocumentRegion());
						appendChild(currentGroupNode);
						// children.add(currentGroupNode);
					}
				}
			}

			if (currentRegion.getType().equals(DTDRegionTypes.LEFT_PAREN)) {
				nesting++;
			}
			if (currentRegion.getType().equals(DTDRegionTypes.RIGHT_PAREN)) {
				nesting--;
				if (nesting == 0 && currentGroupNode != null) {
					currentGroupNode.addRegion(currentRegion);
					// peek at next region to see if it is an occur region. if
					// so, add it to the groupnode
					if (iter.hasNext()) {
						ITextRegion nextRegion = iter.next();
						if (nextRegion.getType().equals(DTDRegionTypes.OCCUR_TYPE)) {
							currentGroupNode.addRegion(nextRegion);
						}
						else {
							// Otherwise, push it back as the next item to be
							// retrieved by a future next() call
							iter.previous();
						}
					}
					currentGroupNode = null;
				}
			}
			if (currentGroupNode != null) {
				currentGroupNode.addRegion(currentRegion);
			}
		}

		if (nesting < 0) {
			// This means we have passed over the right paren that marks the
			// end of our grouping.
			// Look for an occurrence region
			while (iter.hasNext()) {
				ITextRegion currentRegion = iter.next();
				if (currentRegion.getType().equals(DTDRegionTypes.OCCUR_TYPE)) {
					// setOccurrence(currentRegion.getText().toCharArray()[0]);
				}
			} // end of while ()
		}

		// for (org.w3c.dom.Node child = getFirstChild(); child != null; child
		// = child.getNextSibling())
		// {
		// System.out.println("child found = " + child);
		// }

		Object[] children = getChildren();
		// System.out.println("children legnth = " + children.length);

		for (int i = 0; i < children.length; i++) {
			DTDNode currentNode = (DTDNode) children[i];
			currentNode.resolveRegions();
		} // end of while ()

	}

	/**
	 * Set the value of connector.
	 * 
	 * @param v
	 *            Value to assign to connector.
	 */
	public void setConnector(char v) {
		if (connector != v) {
			connector = v;
			// walk through our kids and see if there is a connector between
			// each sibling. if not, create one and set the connector. if
			// there is
			// then just change the text of the connector
			Object[] children = getChildren();
			if (children.length <= 1) {
				// there won't be any connector existing between the children
				// just notify a change in the node and return;
				getDTDFile().notifyNodeChanged(this);
				return;
			}
			beginRecording(this, DTDCoreMessages._UI_LABEL_CM_GRP_NODE_CONNECTOR); //$NON-NLS-1$
			for (int i = 0; i < children.length - 1; i++) {
				DTDNode childA = (DTDNode) children[i];
				DTDNode childB = (DTDNode) children[i + 1];

				// create a stream between the two siblings and walk it
				// note that this stream includes the last region of the first
				// sibling and the first region of the next sibling.
				// both these should be ignored
				RegionIterator iter = new RegionIterator(getStructuredDTDDocumentRegion(), childA.getEndOffset(), childB.getStartOffset());
				// skip the first region which is the last region of childA

				// do we still need this
				// iter.next();
				ITextRegion currentRegion = null;
				boolean foundConnector = false;
				while (iter.hasNext() && currentRegion != childB.getStartRegion()) {
					currentRegion = iter.next();
					if (currentRegion.getType() == DTDRegionTypes.CONNECTOR) {
						foundConnector = true;
						// Region oldRegion = currentRegion.createCopy();
						// found a connector! on to the next sibling pair
						// currentRegion.updateText(String.valueOf(v));
						replaceText(this, getStructuredDTDDocumentRegion().getStartOffset(currentRegion), 1, String.valueOf(connector));
						// changeStructuredDocument(oldRegion, currentRegion);
						break;
					}
				}

				if (!foundConnector) {
					// if we're here, that means we need to insert a new
					// connector region after childA
					replaceText(this, childA.getEndOffset(), 0, String.valueOf(connector));
					// DTDRegion connectorRegion = new
					// DTDRegion(DTDRegionTypes.CONNECTOR,
					// childA.getEndOffset(), 1);
					// insertIntoStructuredDocument(connectorRegion);
				}
			}
			endRecording(this);
		}
	}

	// public Object[] getChildren()
	// {
	// return children.toArray();
	// }
}// CMGroupNode
