/*
 * [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();
        }
    }
}
