/*
 [The "BSD license"]
 Copyright (c) 2005-2009 Terence Parr
 All rights reserved.

 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions
 are met:
 1. Redistributions of source code must retain the above copyright
     notice, this list of conditions and the following disclaimer.
 2. Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in the
     documentation and/or other materials provided with the distribution.
 3. The name of the author may not be used to endorse or promote products
     derived from this software without specific prior written permission.

 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package org.antlr.runtime.tree;

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

/** A generic list of elements tracked in an alternative to be used in
 *  a -&gt; rewrite rule.  We need to subclass to fill in the next() method,
 *  which returns either an AST node wrapped around a token payload or
 *  an existing subtree.
 *
 *  Once you start next()ing, do not try to add more elements.  It will
 *  break the cursor tracking I believe.
 *
 *  @see org.antlr.runtime.tree.RewriteRuleSubtreeStream
 *  @see org.antlr.runtime.tree.RewriteRuleTokenStream
 *
 *  TODO: add mechanism to detect/puke on modification after reading from stream
 */
public abstract class RewriteRuleElementStream {
	/** Cursor 0..n-1.  If singleElement!=null, cursor is 0 until you next(),
	 *  which bumps it to 1 meaning no more elements.
	 */
	protected int cursor = 0;

	/** Track single elements w/o creating a list.  Upon 2nd add, alloc list */
	protected Object singleElement;

	/** The list of tokens or subtrees we are tracking */
	protected List<Object> elements;

	/** Once a node / subtree has been used in a stream, it must be dup'd
	 *  from then on.  Streams are reset after subrules so that the streams
	 *  can be reused in future subrules.  So, reset must set a dirty bit.
	 *  If dirty, then next() always returns a dup.
	 *
	 *  I wanted to use "naughty bit" here, but couldn't think of a way
	 *  to use "naughty".
	 *
	 *  TODO: unused?
	 */
	protected boolean dirty = false;

	/** The element or stream description; usually has name of the token or
	 *  rule reference that this list tracks.  Can include rulename too, but
	 *  the exception would track that info.
	 */
	protected String elementDescription;
	protected TreeAdaptor adaptor;

	public RewriteRuleElementStream(TreeAdaptor adaptor, String elementDescription) {
		this.elementDescription = elementDescription;
		this.adaptor = adaptor;
	}

	/** Create a stream with one element */
	@SuppressWarnings("OverridableMethodCallInConstructor")
	public RewriteRuleElementStream(TreeAdaptor adaptor,
									String elementDescription,
									Object oneElement)
	{
		this(adaptor, elementDescription);
		add(oneElement);
	}

	/** Create a stream, but feed off an existing list */
	public RewriteRuleElementStream(TreeAdaptor adaptor,
									String elementDescription,
									List<Object> elements)
	{
		this(adaptor, elementDescription);
		this.singleElement = null;
		this.elements = elements;
	}

	/** Reset the condition of this stream so that it appears we have
	 *  not consumed any of its elements.  Elements themselves are untouched.
	 *  Once we reset the stream, any future use will need duplicates.  Set
	 *  the dirty bit.
	 */
	public void reset() {
		cursor = 0;
		dirty = true;
	}

	public void add(Object el) {
		//System.out.println("add '"+elementDescription+"' is "+el);
		if ( el==null ) {
			return;
		}
		if ( elements!=null ) { // if in list, just add
			elements.add(el);
			return;
		}
		if ( singleElement == null ) { // no elements yet, track w/o list
			singleElement = el;
			return;
		}
		// adding 2nd element, move to list
		elements = new ArrayList<Object>(5);
		elements.add(singleElement);
		singleElement = null;
		elements.add(el);
	}

	/** Return the next element in the stream.  If out of elements, throw
	 *  an exception unless size()==1.  If size is 1, then return elements[0].
	 *  Return a duplicate node/subtree if stream is out of elements and
	 *  size==1.  If we've already used the element, dup (dirty bit set).
	 */
	public Object nextTree() {
		int n = size();
		if ( dirty || (cursor>=n && n==1) ) {
			// if out of elements and size is 1, dup
			Object el = _next();
			return dup(el);
		}
		// test size above then fetch
		Object el = _next();
		return el;
	}

	/** do the work of getting the next element, making sure that it's
	 *  a tree node or subtree.  Deal with the optimization of single-
	 *  element list versus list of size &gt; 1.  Throw an exception
	 *  if the stream is empty or we're out of elements and size&gt;1.
	 *  protected so you can override in a subclass if necessary.
	 */
	protected Object _next() {
		int n = size();
		if ( n ==0 ) {
			throw new RewriteEmptyStreamException(elementDescription);
		}
		if ( cursor>= n) { // out of elements?
			if ( n ==1 ) {  // if size is 1, it's ok; return and we'll dup
				return toTree(singleElement);
			}
			// out of elements and size was not 1, so we can't dup
			throw new RewriteCardinalityException(elementDescription);
		}
		// we have elements
		if ( singleElement!=null ) {
			cursor++; // move cursor even for single element list
			return toTree(singleElement);
		}
		// must have more than one in list, pull from elements
		Object o = toTree(elements.get(cursor));
		cursor++;
		return o;
	}

	/** When constructing trees, sometimes we need to dup a token or AST
	 * 	subtree.  Dup'ing a token means just creating another AST node
	 *  around it.  For trees, you must call the adaptor.dupTree() unless
	 *  the element is for a tree root; then it must be a node dup.
	 */
	protected abstract Object dup(Object el);

	/** Ensure stream emits trees; tokens must be converted to AST nodes.
	 *  AST nodes can be passed through unmolested.
	 */
	protected Object toTree(Object el) {
		return el;
	}

	public boolean hasNext() {
		 return (singleElement != null && cursor < 1) ||
			   (elements!=null && cursor < elements.size());
	}

	public int size() {
		int n = 0;
		if ( singleElement != null ) {
			n = 1;
		}
		if ( elements!=null ) {
			return elements.size();
		}
		return n;
	}

	public String getDescription() {
		return elementDescription;
	}
}
