/*******************************************************************************
 * Copyright (c) 2001, 2005 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
