/*
 * [The "BSD licence"]
 * Copyright (c) 2005-2008 Terence Parr
 * All rights reserved.
 *
 * Conversion to C#:
 * Copyright (c) 2008-2009 Sam Harwell, Pixel Mine, Inc.
 * 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.
 */

namespace Antlr.Runtime.Tree
{
    using System.Collections.Generic;
    using Antlr.Runtime.Misc;

    using StringBuilder = System.Text.StringBuilder;
    using NotSupportedException = System.NotSupportedException;

    [System.Serializable]
    public class CommonTreeNodeStream : LookaheadStream<object>, ITreeNodeStream
    {
        public const int DEFAULT_INITIAL_BUFFER_SIZE = 100;
        public const int INITIAL_CALL_STACK_SIZE = 10;

        /** <summary>Pull nodes from which tree?</summary> */
        object _root;

        /** <summary>If this tree (root) was created from a token stream, track it.</summary> */
        protected ITokenStream tokens;

        /** <summary>What tree adaptor was used to build these trees</summary> */
        [System.NonSerialized]
        ITreeAdaptor _adaptor;

        /** The tree iterator we are using */
        TreeIterator _it;

        /** <summary>Stack of indexes used for push/pop calls</summary> */
        Stack<int> _calls;

        /** <summary>Tree (nil A B C) trees like flat A B C streams</summary> */
        bool _hasNilRoot = false;

        /** <summary>Tracks tree depth.  Level=0 means we're at root node level.</summary> */
        int _level = 0;

        public CommonTreeNodeStream( object tree )
            : this( new CommonTreeAdaptor(), tree )
        {
        }

        public CommonTreeNodeStream( ITreeAdaptor adaptor, object tree )
        {
            this._root = tree;
            this._adaptor = adaptor;
            _it = new TreeIterator( adaptor, _root );
        }

        #region Properties

        public virtual string SourceName
        {
            get
            {
                if ( TokenStream == null )
                    return null;

                return TokenStream.SourceName;
            }
        }

        public virtual ITokenStream TokenStream
        {
            get
            {
                return tokens;
            }
            set
            {
                tokens = value;
            }
        }

        public virtual ITreeAdaptor TreeAdaptor
        {
            get
            {
                return _adaptor;
            }

            set
            {
                _adaptor = value;
            }
        }

        public virtual object TreeSource
        {
            get
            {
                return _root;
            }
        }

        public virtual bool UniqueNavigationNodes
        {
            get
            {
                return false;
            }

            set
            {
            }
        }

        #endregion

        public virtual void Reset()
        {
            base.Clear();
            _it.Reset();
            _hasNilRoot = false;
            _level = 0;
            if ( _calls != null )
                _calls.Clear();
        }

        public override object NextElement()
        {
            _it.MoveNext();
            object t = _it.Current;
            //System.out.println("pulled "+adaptor.getType(t));
            if ( t == _it.up )
            {
                _level--;
                if ( _level == 0 && _hasNilRoot )
                {
                    _it.MoveNext();
                    return _it.Current; // don't give last UP; get EOF
                }
            }
            else if ( t == _it.down )
            {
                _level++;
            }

            if ( _level == 0 && TreeAdaptor.IsNil( t ) )
            {
                // if nil root, scarf nil, DOWN
                _hasNilRoot = true;
                _it.MoveNext();
                t = _it.Current; // t is now DOWN, so get first real node next
                _level++;
                _it.MoveNext();
                t = _it.Current;
            }

            return t;
        }

        public override bool IsEndOfFile(object o)
        {
            return TreeAdaptor.GetType(o) == CharStreamConstants.EndOfFile;
        }

        public virtual int LA( int i )
        {
            return TreeAdaptor.GetType( LT( i ) );
        }

        /** Make stream jump to a new location, saving old location.
         *  Switch back with pop().
         */
        public virtual void Push( int index )
        {
            if ( _calls == null )
            {
                _calls = new Stack<int>();
            }
            _calls.Push( _p ); // save current index
            Seek( index );
        }

        /** Seek back to previous index saved during last push() call.
         *  Return top of stack (return index).
         */
        public virtual int Pop()
        {
            int ret = _calls.Pop();
            Seek( ret );
            return ret;
        }

        #region Tree rewrite interface

        public virtual void ReplaceChildren( object parent, int startChildIndex, int stopChildIndex, object t )
        {
            if ( parent != null )
            {
                TreeAdaptor.ReplaceChildren( parent, startChildIndex, stopChildIndex, t );
            }
        }

        #endregion

        public virtual string ToString( object start, object stop )
        {
            // we'll have to walk from start to stop in tree; we're not keeping
            // a complete node stream buffer
            return "n/a";
        }

        /** <summary>For debugging; destructive: moves tree iterator to end.</summary> */
        public virtual string ToTokenTypeString()
        {
            Reset();
            StringBuilder buf = new StringBuilder();
            object o = LT( 1 );
            int type = TreeAdaptor.GetType( o );
            while ( type != TokenTypes.EndOfFile )
            {
                buf.Append( " " );
                buf.Append( type );
                Consume();
                o = LT( 1 );
                type = TreeAdaptor.GetType( o );
            }
            return buf.ToString();
        }
    }
}
