/*
 * [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.Debug
{
    using Obsolete = System.ObsoleteAttribute;
    using ITreeAdaptor = Antlr.Runtime.Tree.ITreeAdaptor;
    using ITreeNodeStream = Antlr.Runtime.Tree.ITreeNodeStream;

    /** <summary>
     *  Debug any tree node stream.  The constructor accepts the stream
     *  and a debug listener.  As node stream calls come in, debug events
     *  are triggered.
     *  </summary>
     */
    public class DebugTreeNodeStream : ITreeNodeStream
    {
        protected IDebugEventListener dbg;
        protected ITreeAdaptor adaptor;
        protected ITreeNodeStream input;
        protected bool initialStreamState = true;

        /** <summary>Track the last mark() call result value for use in rewind().</summary> */
        protected int lastMarker;

        public DebugTreeNodeStream( ITreeNodeStream input,
                                   IDebugEventListener dbg )
        {
            this.input = input;
            this.adaptor = input.TreeAdaptor;
            this.input.UniqueNavigationNodes = true;
            DebugListener = dbg;
        }

        #region Properties
        public virtual IDebugEventListener DebugListener
        {
            get
            {
                return dbg;
            }
            set
            {
                dbg = value;
            }
        }
        public virtual int Index
        {
            get
            {
                return input.Index;
            }
        }
        public virtual ITokenStream TokenStream
        {
            get
            {
                return input.TokenStream;
            }
        }
        public virtual ITreeAdaptor TreeAdaptor
        {
            get
            {
                return adaptor;
            }
        }
        public virtual object TreeSource
        {
            get
            {
                return input;
            }
        }
        /** <summary>
         *  It is normally this object that instructs the node stream to
         *  create unique nav nodes, but to satisfy interface, we have to
         *  define it.  It might be better to ignore the parameter but
         *  there might be a use for it later, so I'll leave.
         *  </summary>
         */
        public bool UniqueNavigationNodes
        {
            get
            {
                return input.UniqueNavigationNodes;
            }
            set
            {
                input.UniqueNavigationNodes = value;
            }
        }

        #endregion

        public virtual void Consume()
        {
            object node = input.LT( 1 );
            input.Consume();
            dbg.ConsumeNode( node );
        }

        public virtual object this[int i]
        {
            get
            {
                return input[i];
            }
        }

        public virtual object LT( int i )
        {
            object node = input.LT( i );
            int ID = adaptor.GetUniqueID( node );
            string text = adaptor.GetText( node );
            int type = adaptor.GetType( node );
            dbg.LT( i, node );
            return node;
        }

        public virtual int LA( int i )
        {
            object node = input.LT( i );
            int ID = adaptor.GetUniqueID( node );
            string text = adaptor.GetText( node );
            int type = adaptor.GetType( node );
            dbg.LT( i, node );
            return type;
        }

        public virtual int Mark()
        {
            lastMarker = input.Mark();
            dbg.Mark( lastMarker );
            return lastMarker;
        }

        public virtual void Rewind( int marker )
        {
            dbg.Rewind( marker );
            input.Rewind( marker );
        }

        public virtual void Rewind()
        {
            dbg.Rewind();
            input.Rewind( lastMarker );
        }

        public virtual void Release( int marker )
        {
        }

        public virtual void Seek( int index )
        {
            // TODO: implement seek in dbg interface
            // db.seek(index);
            input.Seek( index );
        }

        public virtual int Count
        {
            get
            {
                return input.Count;
            }
        }

        public virtual string SourceName
        {
            get
            {
                return TokenStream.SourceName;
            }
        }

        public virtual void ReplaceChildren( object parent, int startChildIndex, int stopChildIndex, object t )
        {
            input.ReplaceChildren( parent, startChildIndex, stopChildIndex, t );
        }

        public virtual string ToString( object start, object stop )
        {
            return input.ToString( start, stop );
        }
    }
}
