/*
 * 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 BaseTree = Antlr.Runtime.Tree.BaseTree;
    using Console = System.Console;
    using Exception = System.Exception;
    using IOException = System.IO.IOException;
    using ITree = Antlr.Runtime.Tree.ITree;
    using Socket = System.Net.Sockets.Socket;
    using SocketException = System.Net.Sockets.SocketException;
    using TextReader = System.IO.TextReader;
    using TextWriter = System.IO.TextWriter;

    public class RemoteDebugEventSocketListener {
        const int MAX_EVENT_ELEMENTS = 8;
        IDebugEventListener listener;
        string machine;
        int port;
        Socket channel = null;
        TextWriter @out;
        TextReader @in;
        string @event;
        /** <summary>Version of ANTLR (dictates events)</summary> */
        public string version;
        public string grammarFileName;
        /** <summary>
         *  Track the last token index we saw during a consume.  If same, then
         *  set a flag that we have a problem.
         *  </summary>
         */
        int previousTokenIndex = -1;
        bool tokenIndexesInvalid = false;

        public class ProxyToken : IToken {
            int index;
            int type;
            int channel;
            int line;
            int charPos;
            string text;
            public ProxyToken(int index) {
                this.index = index;
            }
            public ProxyToken(int index, int type, int channel,
                              int line, int charPos, string text) {
                this.index = index;
                this.type = type;
                this.channel = channel;
                this.line = line;
                this.charPos = charPos;
                this.text = text;
            }

            #region IToken Members
            public string Text {
                get {
                    return text;
                }
                set {
                    text = value;
                }
            }

            public int Type {
                get {
                    return type;
                }
                set {
                    type = value;
                }
            }

            public int Line {
                get {
                    return line;
                }
                set {
                    line = value;
                }
            }

            public int CharPositionInLine {
                get {
                    return charPos;
                }
                set {
                    charPos = value;
                }
            }

            public int Channel {
                get {
                    return channel;
                }
                set {
                    channel = value;
                }
            }

            public int StartIndex {
                get {
                    return -1;
                }
                set {
                }
            }

            public int StopIndex {
                get {
                    return -1;
                }
                set {
                }
            }

            public int TokenIndex {
                get {
                    return index;
                }
                set {
                    index = value;
                }
            }

            public ICharStream InputStream {
                get {
                    return null;
                }
                set {
                }
            }

            #endregion

            public override string ToString() {
                string channelStr = "";
                if (channel != TokenChannels.Default) {
                    channelStr = ",channel=" + channel;
                }
                return "[" + Text + "/<" + type + ">" + channelStr + "," + line + ":" + CharPositionInLine + ",@" + index + "]";
            }
        }

        public class ProxyTree : BaseTree {
            public int ID;
            int type;
            int line = 0;
            public int charPos = -1;
            public int tokenIndex = -1;
            string text;

            public ProxyTree(int ID, int type, int line, int charPos, int tokenIndex, string text) {
                this.ID = ID;
                this.type = type;
                this.line = line;
                this.charPos = charPos;
                this.tokenIndex = tokenIndex;
                this.text = text;
            }

            public ProxyTree(int ID) {
                this.ID = ID;
            }

            #region Properties
            public override string Text {
                get {
                    return text;
                }
                set {
                }
            }
            public override int TokenStartIndex {
                get {
                    return tokenIndex;
                }
                set {
                }
            }
            public override int TokenStopIndex {
                get {
                    return 0;
                }
                set {
                }
            }
            public override int Type {
                get {
                    return type;
                }
                set {
                }
            }
            #endregion

            public override ITree DupNode() {
                return null;
            }

            public override string ToString() {
                return "fix this";
            }
        }

        public RemoteDebugEventSocketListener(IDebugEventListener listener,
                                              string machine,
                                              int port) {
            this.listener = listener;
            this.machine = machine;
            this.port = port;

            if (!OpenConnection()) {
                throw new SocketException();
            }
        }

        protected virtual void EventHandler() {
            try {
                Handshake();
                @event = @in.ReadLine();
                while (@event != null) {
                    Dispatch(@event);
                    Ack();
                    @event = @in.ReadLine();
                }
            } catch (Exception e) {
                Console.Error.WriteLine(e);
                ExceptionExtensions.PrintStackTrace(e, Console.Error);
            } finally {
                CloseConnection();
            }
        }

        protected virtual bool OpenConnection() {
            bool success = false;
            try {
                throw new System.NotImplementedException();
                //channel = new Socket( machine, port );
                //channel.setTcpNoDelay( true );
                //OutputStream os = channel.getOutputStream();
                //OutputStreamWriter osw = new OutputStreamWriter( os, "UTF8" );
                //@out = new PrintWriter( new BufferedWriter( osw ) );
                //InputStream @is = channel.getInputStream();
                //InputStreamReader isr = new InputStreamReader( @is, "UTF8" );
                //@in = new BufferedReader( isr );
                //success = true;
            } catch (Exception e) {
                Console.Error.WriteLine(e);
            }
            return success;
        }

        protected virtual void CloseConnection() {
            try {
                @in.Close();
                @in = null;
                @out.Close();
                @out = null;
                channel.Close();
                channel = null;
            } catch (Exception e) {
                Console.Error.WriteLine(e);
                ExceptionExtensions.PrintStackTrace(e, Console.Error);
            } finally {
                if (@in != null) {
                    try {
                        @in.Close();
                    } catch (IOException ioe) {
                        Console.Error.WriteLine(ioe);
                    }
                }
                if (@out != null) {
                    @out.Close();
                }
                if (channel != null) {
                    try {
                        channel.Close();
                    } catch (IOException ioe) {
                        Console.Error.WriteLine(ioe);
                    }
                }
            }

        }

        protected virtual void Handshake() {
            string antlrLine = @in.ReadLine();
            string[] antlrElements = GetEventElements(antlrLine);
            version = antlrElements[1];
            string grammarLine = @in.ReadLine();
            string[] grammarElements = GetEventElements(grammarLine);
            grammarFileName = grammarElements[1];
            Ack();
            listener.Commence(); // inform listener after handshake
        }

        protected virtual void Ack() {
            @out.WriteLine("ack");
            @out.Flush();
        }

        protected virtual void Dispatch(string line) {
            //JSystem.@out.println( "event: " + line );
            string[] elements = GetEventElements(line);
            if (elements == null || elements[0] == null) {
                Console.Error.WriteLine("unknown debug event: " + line);
                return;
            }
            if (elements[0].Equals("enterRule")) {
                listener.EnterRule(elements[1], elements[2]);
            } else if (elements[0].Equals("exitRule")) {
                listener.ExitRule(elements[1], elements[2]);
            } else if (elements[0].Equals("enterAlt")) {
                listener.EnterAlt(int.Parse(elements[1]));
            } else if (elements[0].Equals("enterSubRule")) {
                listener.EnterSubRule(int.Parse(elements[1]));
            } else if (elements[0].Equals("exitSubRule")) {
                listener.ExitSubRule(int.Parse(elements[1]));
            } else if (elements[0].Equals("enterDecision")) {
                listener.EnterDecision(int.Parse(elements[1]), elements[2].Equals("true"));
            } else if (elements[0].Equals("exitDecision")) {
                listener.ExitDecision(int.Parse(elements[1]));
            } else if (elements[0].Equals("location")) {
                listener.Location(int.Parse(elements[1]),
                                  int.Parse(elements[2]));
            } else if (elements[0].Equals("consumeToken")) {
                ProxyToken t = DeserializeToken(elements, 1);
                if (t.TokenIndex == previousTokenIndex) {
                    tokenIndexesInvalid = true;
                }
                previousTokenIndex = t.TokenIndex;
                listener.ConsumeToken(t);
            } else if (elements[0].Equals("consumeHiddenToken")) {
                ProxyToken t = DeserializeToken(elements, 1);
                if (t.TokenIndex == previousTokenIndex) {
                    tokenIndexesInvalid = true;
                }
                previousTokenIndex = t.TokenIndex;
                listener.ConsumeHiddenToken(t);
            } else if (elements[0].Equals("LT")) {
                IToken t = DeserializeToken(elements, 2);
                listener.LT(int.Parse(elements[1]), t);
            } else if (elements[0].Equals("mark")) {
                listener.Mark(int.Parse(elements[1]));
            } else if (elements[0].Equals("rewind")) {
                if (elements[1] != null) {
                    listener.Rewind(int.Parse(elements[1]));
                } else {
                    listener.Rewind();
                }
            } else if (elements[0].Equals("beginBacktrack")) {
                listener.BeginBacktrack(int.Parse(elements[1]));
            } else if (elements[0].Equals("endBacktrack")) {
                int level = int.Parse(elements[1]);
                int successI = int.Parse(elements[2]);
                listener.EndBacktrack(level, successI == DebugEventListenerConstants.True);
            } else if (elements[0].Equals("exception")) {
#if true
                throw new System.NotImplementedException();
#else
                string excName = elements[1];
                string indexS = elements[2];
                string lineS = elements[3];
                string posS = elements[4];
                Class excClass = null;
                try
                {
                    excClass = Class.forName( excName );
                    RecognitionException e =
                        (RecognitionException)excClass.newInstance();
                    e.index = int.Parse( indexS );
                    e.line = int.Parse( lineS );
                    e.charPositionInLine = int.Parse( posS );
                    listener.recognitionException( e );
                }
                catch ( ClassNotFoundException cnfe )
                {
                    Console.Error.println( "can't find class " + cnfe );
                    cnfe.printStackTrace( Console.Error );
                }
                catch ( InstantiationException ie )
                {
                    Console.Error.println( "can't instantiate class " + ie );
                    ie.printStackTrace( Console.Error );
                }
                catch ( IllegalAccessException iae )
                {
                    Console.Error.println( "can't access class " + iae );
                    iae.printStackTrace( Console.Error );
                }
#endif
            } else if (elements[0].Equals("beginResync")) {
                listener.BeginResync();
            } else if (elements[0].Equals("endResync")) {
                listener.EndResync();
            } else if (elements[0].Equals("terminate")) {
                listener.Terminate();
            } else if (elements[0].Equals("semanticPredicate")) {
                bool result = bool.Parse(elements[1]);
                string predicateText = elements[2];
                predicateText = UnEscapeNewlines(predicateText);
                listener.SemanticPredicate(result,
                                           predicateText);
            } else if (elements[0].Equals("consumeNode")) {
                ProxyTree node = DeserializeNode(elements, 1);
                listener.ConsumeNode(node);
            } else if (elements[0].Equals("LN")) {
                int i = int.Parse(elements[1]);
                ProxyTree node = DeserializeNode(elements, 2);
                listener.LT(i, node);
            } else if (elements[0].Equals("createNodeFromTokenElements")) {
                int ID = int.Parse(elements[1]);
                int type = int.Parse(elements[2]);
                string text = elements[3];
                text = UnEscapeNewlines(text);
                ProxyTree node = new ProxyTree(ID, type, -1, -1, -1, text);
                listener.CreateNode(node);
            } else if (elements[0].Equals("createNode")) {
                int ID = int.Parse(elements[1]);
                int tokenIndex = int.Parse(elements[2]);
                // create dummy node/token filled with ID, tokenIndex
                ProxyTree node = new ProxyTree(ID);
                ProxyToken token = new ProxyToken(tokenIndex);
                listener.CreateNode(node, token);
            } else if (elements[0].Equals("nilNode")) {
                int ID = int.Parse(elements[1]);
                ProxyTree node = new ProxyTree(ID);
                listener.NilNode(node);
            } else if (elements[0].Equals("errorNode")) {
                // TODO: do we need a special tree here?
                int ID = int.Parse(elements[1]);
                int type = int.Parse(elements[2]);
                string text = elements[3];
                text = UnEscapeNewlines(text);
                ProxyTree node = new ProxyTree(ID, type, -1, -1, -1, text);
                listener.ErrorNode(node);
            } else if (elements[0].Equals("becomeRoot")) {
                int newRootID = int.Parse(elements[1]);
                int oldRootID = int.Parse(elements[2]);
                ProxyTree newRoot = new ProxyTree(newRootID);
                ProxyTree oldRoot = new ProxyTree(oldRootID);
                listener.BecomeRoot(newRoot, oldRoot);
            } else if (elements[0].Equals("addChild")) {
                int rootID = int.Parse(elements[1]);
                int childID = int.Parse(elements[2]);
                ProxyTree root = new ProxyTree(rootID);
                ProxyTree child = new ProxyTree(childID);
                listener.AddChild(root, child);
            } else if (elements[0].Equals("setTokenBoundaries")) {
                int ID = int.Parse(elements[1]);
                ProxyTree node = new ProxyTree(ID);
                listener.SetTokenBoundaries(
                    node,
                    int.Parse(elements[2]),
                    int.Parse(elements[3]));
            } else {
                Console.Error.WriteLine("unknown debug event: " + line);
            }
        }

        protected virtual ProxyTree DeserializeNode(string[] elements, int offset) {
            int ID = int.Parse(elements[offset + 0]);
            int type = int.Parse(elements[offset + 1]);
            int tokenLine = int.Parse(elements[offset + 2]);
            int charPositionInLine = int.Parse(elements[offset + 3]);
            int tokenIndex = int.Parse(elements[offset + 4]);
            string text = elements[offset + 5];
            text = UnEscapeNewlines(text);
            return new ProxyTree(ID, type, tokenLine, charPositionInLine, tokenIndex, text);
        }

        protected virtual ProxyToken DeserializeToken(string[] elements,
                                              int offset) {
            string indexS = elements[offset + 0];
            string typeS = elements[offset + 1];
            string channelS = elements[offset + 2];
            string lineS = elements[offset + 3];
            string posS = elements[offset + 4];
            string text = elements[offset + 5];
            text = UnEscapeNewlines(text);
            int index = int.Parse(indexS);
            ProxyToken t =
                new ProxyToken(index,
                               int.Parse(typeS),
                               int.Parse(channelS),
                               int.Parse(lineS),
                               int.Parse(posS),
                               text);
            return t;
        }

        /** <summary>Create a thread to listen to the remote running recognizer</summary> */
        public virtual void Start() {
            System.Threading.Thread t = new System.Threading.Thread(Run);
            t.Start();
        }

        public virtual void Run() {
            EventHandler();
        }

        #region Misc

        public virtual string[] GetEventElements(string @event) {
            if (@event == null) {
                return null;
            }
            string[] elements = new string[MAX_EVENT_ELEMENTS];
            string str = null; // a string element if present (must be last)
            try {
                int firstQuoteIndex = @event.IndexOf('"');
                if (firstQuoteIndex >= 0) {
                    // treat specially; has a string argument like "a comment\n
                    // Note that the string is terminated by \n not end quote.
                    // Easier to parse that way.
                    string eventWithoutString = @event.Substring(0, firstQuoteIndex);
                    str = @event.Substring(firstQuoteIndex + 1);
                    @event = eventWithoutString;
                }
                StringTokenizer st = new StringTokenizer(@event, "\t", false);
                int i = 0;
                while (st.hasMoreTokens()) {
                    if (i >= MAX_EVENT_ELEMENTS) {
                        // ErrorManager.internalError("event has more than "+MAX_EVENT_ELEMENTS+" args: "+event);
                        return elements;
                    }
                    elements[i] = st.nextToken();
                    i++;
                }
                if (str != null) {
                    elements[i] = str;
                }
            } catch (Exception e) {
                ExceptionExtensions.PrintStackTrace(e, Console.Error);
            }
            return elements;
        }

        protected virtual string UnEscapeNewlines(string txt) {
            // this unescape is slow but easy to understand
            txt = StringExtensions.replaceAll(txt, "%0A", "\n");  // unescape \n
            txt = StringExtensions.replaceAll(txt, "%0D", "\r");  // unescape \r
            txt = StringExtensions.replaceAll(txt, "%25", "%");   // undo escaped escape chars
            return txt;
        }

        public virtual bool TokenIndexesAreInvalid() {
            return false;
            //return tokenIndexesInvalid;
        }

        #endregion

    }
}
