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

import java.util.List;

import org.eclipse.swt.graphics.Image;
import org.eclipse.wst.dtd.core.internal.text.RegionIterator;
import org.eclipse.wst.dtd.core.parser.DTDRegionTypes;
import org.eclipse.wst.dtd.core.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, DTDPlugin.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, DTDPlugin.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(getStructuredDocumentRegion(), 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 = getStructuredDocumentRegion().getText(currentRegion).charAt(0);
					return connector;
				}
			}
		}
		return connector;
	}

	public Image getImage() {
		DTDPlugin resourcePlugin = DTDPlugin.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;
		boolean isLastChild = position == children.length;
		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, DTDPlugin.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();
		// we skip past the first left paren we see since that is the
		// beginning of our own node
		boolean isConnectorSet = false;
		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(), getStructuredDocumentRegion());
					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(), getStructuredDocumentRegion());
					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(), getStructuredDocumentRegion());
						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, DTDPlugin.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(getStructuredDocumentRegion(), 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, getStructuredDocumentRegion().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
