/*
 * Note to JL: Refactored extension methods
 * 
 * [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 Antlr.Runtime.JavaExtensions;

    using Console = System.Console;
    using IOException = System.IO.IOException;
    using ITreeNodeStream = Antlr.Runtime.Tree.ITreeNodeStream;
    using TreeParser = Antlr.Runtime.Tree.TreeParser;

    public class DebugTreeParser : TreeParser {
        /** <summary>Who to notify when events in the parser occur.</summary> */
        public IDebugEventListener dbg = null;

        /** <summary>
         *  Used to differentiate between fixed lookahead and cyclic DFA decisions
         *  while profiling.
         *  </summary>
         */
        public bool isCyclicDecision = false;

        /** <summary>
         *  Create a normal parser except wrap the token stream in a debug
         *  proxy that fires consume events.
         *  </summary>
         */
        public DebugTreeParser(ITreeNodeStream input, IDebugEventListener dbg, RecognizerSharedState state)
            : base(input is DebugTreeNodeStream ? input : new DebugTreeNodeStream(input, dbg), state) {
            SetDebugListener(dbg);
        }

        public DebugTreeParser(ITreeNodeStream input, RecognizerSharedState state)
            : base(input is DebugTreeNodeStream ? input : new DebugTreeNodeStream(input, null), state) {
        }

        public DebugTreeParser(ITreeNodeStream input, IDebugEventListener dbg)
            : this(input is DebugTreeNodeStream ? input : new DebugTreeNodeStream(input, dbg), dbg, null) {
        }

        public override IDebugEventListener DebugListener {
            get {
                return dbg;
            }
        }

        /** <summary>
         *  Provide a new debug event listener for this parser.  Notify the
         *  input stream too that it should send events to this listener.
         *  </summary>
         */
        public virtual void SetDebugListener(IDebugEventListener value) {
            if (input is DebugTreeNodeStream)
                ((DebugTreeNodeStream)input).DebugListener = value;

            this.dbg = value;
        }

        public virtual void ReportError(IOException e) {
            Console.Error.WriteLine(e);
            ExceptionExtensions.PrintStackTrace(e, Console.Error);
        }

        public override void ReportError(RecognitionException e) {
            dbg.RecognitionException(e);
        }

        protected override object GetMissingSymbol(IIntStream input,
                                          RecognitionException e,
                                          int expectedTokenType,
                                          BitSet follow) {
            object o = base.GetMissingSymbol(input, e, expectedTokenType, follow);
            dbg.ConsumeNode(o);
            return o;
        }

        public override void BeginResync() {
            dbg.BeginResync();
        }

        public override void EndResync() {
            dbg.EndResync();
        }

        public virtual void BeginBacktrack(int level) {
            dbg.BeginBacktrack(level);
        }

        public virtual void EndBacktrack(int level, bool successful) {
            dbg.EndBacktrack(level, successful);
        }
    }
}
