/*******************************************************************************
 * 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.text.IStructuredDocumentRegion;
import org.eclipse.wst.sse.core.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, DTDCorePlugin.getDTDString("_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, DTDCorePlugin.getDTDString("_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, DTDCorePlugin.getDTDString("_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, DTDCorePlugin.getDTDString("_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
