/*
 * [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.
 */

// TODO: build indexes for wizard
//#define BUILD_INDEXES

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

    using IList = System.Collections.IList;
#if BUILD_INDEXES
    using IDictionary = System.Collections.IDictionary;
#endif

    /** <summary>
     *  Build and navigate trees with this object.  Must know about the names
     *  of tokens so you have to pass in a map or array of token names (from which
     *  this class can build the map).  I.e., Token DECL means nothing unless the
     *  class can translate it to a token type.
     *  </summary>
     *
     *  <remarks>
     *  In order to create nodes and navigate, this class needs a TreeAdaptor.
     *
     *  This class can build a token type -> node index for repeated use or for
     *  iterating over the various nodes with a particular type.
     *
     *  This class works in conjunction with the TreeAdaptor rather than moving
     *  all this functionality into the adaptor.  An adaptor helps build and
     *  navigate trees using methods.  This class helps you do it with string
     *  patterns like "(A B C)".  You can create a tree from that pattern or
     *  match subtrees against it.
     *  </remarks>
     */
    public class TreeWizard
    {
        protected ITreeAdaptor adaptor;
        protected IDictionary<string, int> tokenNameToTypeMap;

        public interface IContextVisitor
        {
            // TODO: should this be called visit or something else?
            void Visit( object t, object parent, int childIndex, IDictionary<string, object> labels );
        }

        public abstract class Visitor : IContextVisitor
        {
            public virtual void Visit( object t, object parent, int childIndex, IDictionary<string, object> labels )
            {
                Visit( t );
            }
            public abstract void Visit( object t );
        }

        class ActionVisitor : Visitor
        {
            System.Action<object> _action;

            public ActionVisitor( System.Action<object> action )
            {
                _action = action;
            }

            public override void Visit( object t )
            {
                _action( t );
            }
        }

        /** <summary>
         *  When using %label:TOKENNAME in a tree for parse(), we must
         *  track the label.
         *  </summary>
         */
        public class TreePattern : CommonTree
        {
            public string label;
            public bool hasTextArg;
            public TreePattern( IToken payload ) :
                base( payload )
            {
            }
            public override string ToString()
            {
                if ( label != null )
                {
                    return "%" + label + ":"; //+ base.ToString();
                }
                else
                {
                    return base.ToString();
                }
            }
        }

        public class WildcardTreePattern : TreePattern
        {
            public WildcardTreePattern( IToken payload ) :
                base( payload )
            {
            }
        }

        /** <summary>This adaptor creates TreePattern objects for use during scan()</summary> */
        public class TreePatternTreeAdaptor : CommonTreeAdaptor
        {
            public override object Create( IToken payload )
            {
                return new TreePattern( payload );
            }
        }

#if BUILD_INDEXES
        // TODO: build indexes for the wizard

        /** <summary>
         *  During fillBuffer(), we can make a reverse index from a set
         *  of token types of interest to the list of indexes into the
         *  node stream.  This lets us convert a node pointer to a
         *  stream index semi-efficiently for a list of interesting
         *  nodes such as function definition nodes (you'll want to seek
         *  to their bodies for an interpreter).  Also useful for doing
         *  dynamic searches; i.e., go find me all PLUS nodes.
         *  </summary>
         */
        protected IDictionary<int, IList<int>> tokenTypeToStreamIndexesMap;

        /** <summary>
         *  If tokenTypesToReverseIndex set to INDEX_ALL then indexing
         *  occurs for all token types.
         *  </summary>
         */
        public static readonly HashSet<int> INDEX_ALL = new HashSet<int>();

        /** <summary>
         *  A set of token types user would like to index for faster lookup.
         *  If this is INDEX_ALL, then all token types are tracked.  If null,
         *  then none are indexed.
         *  </summary>
         */
        protected HashSet<int> tokenTypesToReverseIndex = null;
#endif

        public TreeWizard( ITreeAdaptor adaptor )
        {
            this.adaptor = adaptor;
        }

        public TreeWizard( ITreeAdaptor adaptor, IDictionary<string, int> tokenNameToTypeMap )
        {
            this.adaptor = adaptor;
            this.tokenNameToTypeMap = tokenNameToTypeMap;
        }

        public TreeWizard( ITreeAdaptor adaptor, string[] tokenNames )
        {
            this.adaptor = adaptor;
            this.tokenNameToTypeMap = ComputeTokenTypes( tokenNames );
        }

        public TreeWizard( string[] tokenNames )
            : this( new CommonTreeAdaptor(), tokenNames )
        {
        }

        /** <summary>
         *  Compute a Map&lt;String, Integer&gt; that is an inverted index of
         *  tokenNames (which maps int token types to names).
         *  </summary>
         */
        public virtual IDictionary<string, int> ComputeTokenTypes( string[] tokenNames )
        {
            IDictionary<string, int> m = new Dictionary<string, int>();
            if ( tokenNames == null )
            {
                return m;
            }
            for ( int ttype = TokenTypes.Min; ttype < tokenNames.Length; ttype++ )
            {
                string name = tokenNames[ttype];
                m[name] = ttype;
            }
            return m;
        }

        /** <summary>Using the map of token names to token types, return the type.</summary> */
        public virtual int GetTokenType( string tokenName )
        {
            if ( tokenNameToTypeMap == null )
            {
                return TokenTypes.Invalid;
            }

            int value;
            if ( tokenNameToTypeMap.TryGetValue( tokenName, out value ) )
                return value;

            return TokenTypes.Invalid;
        }

        /** <summary>
         *  Walk the entire tree and make a node name to nodes mapping.
         *  For now, use recursion but later nonrecursive version may be
         *  more efficient.  Returns Map&lt;Integer, List&gt; where the List is
         *  of your AST node type.  The Integer is the token type of the node.
         *  </summary>
         *
         *  <remarks>
         *  TODO: save this index so that find and visit are faster
         *  </remarks>
         */
        public IDictionary<int, IList> Index( object t )
        {
            IDictionary<int, IList> m = new Dictionary<int, IList>();
            IndexCore( t, m );
            return m;
        }

        /** <summary>Do the work for index</summary> */
        protected virtual void IndexCore( object t, IDictionary<int, IList> m )
        {
            if ( t == null )
            {
                return;
            }
            int ttype = adaptor.GetType( t );
            IList elements;
            if ( !m.TryGetValue( ttype, out elements ) || elements == null )
            {
                elements = new List<object>();
                m[ttype] = elements;
            }
            elements.Add( t );
            int n = adaptor.GetChildCount( t );
            for ( int i = 0; i < n; i++ )
            {
                object child = adaptor.GetChild( t, i );
                IndexCore( child, m );
            }
        }

        class FindTreeWizardVisitor : TreeWizard.Visitor
        {
            IList _nodes;
            public FindTreeWizardVisitor( IList nodes )
            {
                _nodes = nodes;
            }
            public override void Visit( object t )
            {
                _nodes.Add( t );
            }
        }
        class FindTreeWizardContextVisitor : TreeWizard.IContextVisitor
        {
            TreeWizard _outer;
            TreePattern _tpattern;
            IList _subtrees;
            public FindTreeWizardContextVisitor( TreeWizard outer, TreePattern tpattern, IList subtrees )
            {
                _outer = outer;
                _tpattern = tpattern;
                _subtrees = subtrees;
            }

            public void Visit( object t, object parent, int childIndex, IDictionary<string, object> labels )
            {
                if ( _outer.ParseCore( t, _tpattern, null ) )
                {
                    _subtrees.Add( t );
                }
            }
        }

        /** <summary>Return a List of tree nodes with token type ttype</summary> */
        public virtual IList Find( object t, int ttype )
        {
            IList nodes = new List<object>();
            Visit( t, ttype, new FindTreeWizardVisitor( nodes ) );
            return nodes;
        }

        /** <summary>Return a List of subtrees matching pattern.</summary> */
        public virtual IList Find( object t, string pattern )
        {
            IList subtrees = new List<object>();
            // Create a TreePattern from the pattern
            TreePatternLexer tokenizer = new TreePatternLexer( pattern );
            TreePatternParser parser =
                new TreePatternParser( tokenizer, this, new TreePatternTreeAdaptor() );
            TreePattern tpattern = (TreePattern)parser.Pattern();
            // don't allow invalid patterns
            if ( tpattern == null ||
                 tpattern.IsNil ||
                 tpattern.GetType() == typeof( WildcardTreePattern ) )
            {
                return null;
            }
            int rootTokenType = tpattern.Type;
            Visit( t, rootTokenType, new FindTreeWizardContextVisitor( this, tpattern, subtrees ) );
            return subtrees;
        }

        public virtual object FindFirst( object t, int ttype )
        {
            return null;
        }

        public virtual object FindFirst( object t, string pattern )
        {
            return null;
        }

        /** <summary>
         *  Visit every ttype node in t, invoking the visitor.  This is a quicker
         *  version of the general visit(t, pattern) method.  The labels arg
         *  of the visitor action method is never set (it's null) since using
         *  a token type rather than a pattern doesn't let us set a label.
         *  </summary>
         */
        public void Visit( object t, int ttype, IContextVisitor visitor )
        {
            VisitCore( t, null, 0, ttype, visitor );
        }

        public void Visit( object t, int ttype, System.Action<object> action )
        {
            Visit( t, ttype, new ActionVisitor( action ) );
        }

        /** <summary>Do the recursive work for visit</summary> */
        protected virtual void VisitCore( object t, object parent, int childIndex, int ttype, IContextVisitor visitor )
        {
            if ( t == null )
            {
                return;
            }
            if ( adaptor.GetType( t ) == ttype )
            {
                visitor.Visit( t, parent, childIndex, null );
            }
            int n = adaptor.GetChildCount( t );
            for ( int i = 0; i < n; i++ )
            {
                object child = adaptor.GetChild( t, i );
                VisitCore( child, t, i, ttype, visitor );
            }
        }

        class VisitTreeWizardContextVisitor : TreeWizard.IContextVisitor
        {
            TreeWizard _outer;
            IContextVisitor _visitor;
            IDictionary<string, object> _labels;
            TreePattern _tpattern;

            public VisitTreeWizardContextVisitor( TreeWizard outer, IContextVisitor visitor, IDictionary<string, object> labels, TreePattern tpattern )
            {
                _outer = outer;
                _visitor = visitor;
                _labels = labels;
                _tpattern = tpattern;
            }

            public void Visit( object t, object parent, int childIndex, IDictionary<string, object> unusedlabels )
            {
                // the unusedlabels arg is null as visit on token type doesn't set.
                _labels.Clear();
                if ( _outer.ParseCore( t, _tpattern, _labels ) )
                {
                    _visitor.Visit( t, parent, childIndex, _labels );
                }
            }
        }

        /** <summary>
         *  For all subtrees that match the pattern, execute the visit action.
         *  The implementation uses the root node of the pattern in combination
         *  with visit(t, ttype, visitor) so nil-rooted patterns are not allowed.
         *  Patterns with wildcard roots are also not allowed.
         *  </summary>
         */
        public void Visit( object t, string pattern, IContextVisitor visitor )
        {
            // Create a TreePattern from the pattern
            TreePatternLexer tokenizer = new TreePatternLexer( pattern );
            TreePatternParser parser =
                new TreePatternParser( tokenizer, this, new TreePatternTreeAdaptor() );
            TreePattern tpattern = (TreePattern)parser.Pattern();
            // don't allow invalid patterns
            if ( tpattern == null ||
                 tpattern.IsNil ||
                 tpattern.GetType() == typeof( WildcardTreePattern ) )
            {
                return;
            }
            IDictionary<string, object> labels = new Dictionary<string, object>(); // reused for each _parse
            int rootTokenType = tpattern.Type;
            Visit( t, rootTokenType, new VisitTreeWizardContextVisitor( this, visitor, labels, tpattern ) );
        }

        /** <summary>
         *  Given a pattern like (ASSIGN %lhs:ID %rhs:.) with optional labels
         *  on the various nodes and '.' (dot) as the node/subtree wildcard,
         *  return true if the pattern matches and fill the labels Map with
         *  the labels pointing at the appropriate nodes.  Return false if
         *  the pattern is malformed or the tree does not match.
         *  </summary>
         *
         *  <remarks>
         *  If a node specifies a text arg in pattern, then that must match
         *  for that node in t.
         *
         *  TODO: what's a better way to indicate bad pattern? Exceptions are a hassle 
         *  </remarks>
         */
        public bool Parse( object t, string pattern, IDictionary<string, object> labels )
        {
            TreePatternLexer tokenizer = new TreePatternLexer( pattern );
            TreePatternParser parser =
                new TreePatternParser( tokenizer, this, new TreePatternTreeAdaptor() );
            TreePattern tpattern = (TreePattern)parser.Pattern();
            /*
            System.out.println("t="+((Tree)t).toStringTree());
            System.out.println("scant="+tpattern.toStringTree());
            */
            bool matched = ParseCore( t, tpattern, labels );
            return matched;
        }

        public bool Parse( object t, string pattern )
        {
            return Parse( t, pattern, null );
        }

        /** <summary>
         *  Do the work for parse. Check to see if the t2 pattern fits the
         *  structure and token types in t1.  Check text if the pattern has
         *  text arguments on nodes.  Fill labels map with pointers to nodes
         *  in tree matched against nodes in pattern with labels.
         *  </summary>
         */
        protected virtual bool ParseCore( object t1, TreePattern tpattern, IDictionary<string, object> labels )
        {
            // make sure both are non-null
            if ( t1 == null || tpattern == null )
            {
                return false;
            }
            // check roots (wildcard matches anything)
            if ( tpattern.GetType() != typeof( WildcardTreePattern ) )
            {
                if ( adaptor.GetType( t1 ) != tpattern.Type )
                {
                    return false;
                }
                // if pattern has text, check node text
                if ( tpattern.hasTextArg && !adaptor.GetText( t1 ).Equals( tpattern.Text ) )
                {
                    return false;
                }
            }
            if ( tpattern.label != null && labels != null )
            {
                // map label in pattern to node in t1
                labels[tpattern.label] = t1;
            }
            // check children
            int n1 = adaptor.GetChildCount( t1 );
            int n2 = tpattern.ChildCount;
            if ( n1 != n2 )
            {
                return false;
            }
            for ( int i = 0; i < n1; i++ )
            {
                object child1 = adaptor.GetChild( t1, i );
                TreePattern child2 = (TreePattern)tpattern.GetChild( i );
                if ( !ParseCore( child1, child2, labels ) )
                {
                    return false;
                }
            }
            return true;
        }

        /** <summary>
         *  Create a tree or node from the indicated tree pattern that closely
         *  follows ANTLR tree grammar tree element syntax:
         *
         *      (root child1 ... child2).
         *  </summary>
         *
         *  <remarks>
         *  You can also just pass in a node: ID
         * 
         *  Any node can have a text argument: ID[foo]
         *  (notice there are no quotes around foo--it's clear it's a string).
         *
         *  nil is a special name meaning "give me a nil node".  Useful for
         *  making lists: (nil A B C) is a list of A B C.
         *  </remarks>
         */
        public virtual object Create( string pattern )
        {
            TreePatternLexer tokenizer = new TreePatternLexer( pattern );
            TreePatternParser parser = new TreePatternParser( tokenizer, this, adaptor );
            object t = parser.Pattern();
            return t;
        }

        /** <summary>
         *  Compare t1 and t2; return true if token types/text, structure match exactly.
         *  The trees are examined in their entirety so that (A B) does not match
         *  (A B C) nor (A (B C)). 
         *  </summary>
         *
         *  <remarks>
         *  TODO: allow them to pass in a comparator
         *  TODO: have a version that is nonstatic so it can use instance adaptor
         *
         *  I cannot rely on the tree node's equals() implementation as I make
         *  no constraints at all on the node types nor interface etc... 
         *  </remarks>
         */
        public static bool Equals( object t1, object t2, ITreeAdaptor adaptor )
        {
            return EqualsCore( t1, t2, adaptor );
        }

        /** <summary>
         *  Compare type, structure, and text of two trees, assuming adaptor in
         *  this instance of a TreeWizard.
         *  </summary>
         */
        public new bool Equals( object t1, object t2 )
        {
            return EqualsCore( t1, t2, adaptor );
        }

        protected static bool EqualsCore( object t1, object t2, ITreeAdaptor adaptor )
        {
            // make sure both are non-null
            if ( t1 == null || t2 == null )
            {
                return false;
            }
            // check roots
            if ( adaptor.GetType( t1 ) != adaptor.GetType( t2 ) )
            {
                return false;
            }
            if ( !adaptor.GetText( t1 ).Equals( adaptor.GetText( t2 ) ) )
            {
                return false;
            }
            // check children
            int n1 = adaptor.GetChildCount( t1 );
            int n2 = adaptor.GetChildCount( t2 );
            if ( n1 != n2 )
            {
                return false;
            }
            for ( int i = 0; i < n1; i++ )
            {
                object child1 = adaptor.GetChild( t1, i );
                object child2 = adaptor.GetChild( t2, i );
                if ( !EqualsCore( child1, child2, adaptor ) )
                {
                    return false;
                }
            }
            return true;
        }

#if BUILD_INDEXES
        // TODO: next stuff taken from CommonTreeNodeStream

        /** <summary>
         *  Given a node, add this to the reverse index tokenTypeToStreamIndexesMap.
         *  You can override this method to alter how indexing occurs.  The
         *  default is to create a
         *
         *    Map&lt;Integer token type,ArrayList&lt;Integer stream index&gt;&gt;
         *  </summary>
         *
         *  <remarks>
         *  This data structure allows you to find all nodes with type INT in order.
         *
         *  If you really need to find a node of type, say, FUNC quickly then perhaps
         *
         *    Map&lt;Integertoken type,Map&lt;Object tree node,Integer stream index&gt;&gt;
         *
         *  would be better for you.  The interior maps map a tree node to
         *  the index so you don't have to search linearly for a specific node.
         *
         *  If you change this method, you will likely need to change
         *  getNodeIndex(), which extracts information.
         *  </remarks>
         */
        protected void fillReverseIndex( object node, int streamIndex )
        {
            //System.out.println("revIndex "+node+"@"+streamIndex);
            if ( tokenTypesToReverseIndex == null )
            {
                return; // no indexing if this is empty (nothing of interest)
            }
            if ( tokenTypeToStreamIndexesMap == null )
            {
                tokenTypeToStreamIndexesMap = new Dictionary<int, IList<int>>(); // first indexing op
            }
            int tokenType = adaptor.getType( node );
            if ( !( tokenTypesToReverseIndex == INDEX_ALL ||
                   tokenTypesToReverseIndex.Contains( tokenType ) ) )
            {
                return; // tokenType not of interest
            }
            IList<int> indexes;

            if ( !tokenTypeToStreamIndexesMap.TryGetValue( tokenType, out indexes ) || indexes == null )
            {
                indexes = new List<int>(); // no list yet for this token type
                indexes.Add( streamIndex ); // not there yet, add
                tokenTypeToStreamIndexesMap[tokenType] = indexes;
            }
            else
            {
                if ( !indexes.Contains( streamIndex ) )
                {
                    indexes.Add( streamIndex ); // not there yet, add
                }
            }
        }

        /** <summary>
         *  Track the indicated token type in the reverse index.  Call this
         *  repeatedly for each type or use variant with Set argument to
         *  set all at once.
         *  </summary>
         *
         *  <param name="tokenType" />
         */
        public void reverseIndex( int tokenType )
        {
            if ( tokenTypesToReverseIndex == null )
            {
                tokenTypesToReverseIndex = new HashSet<int>();
            }
            else if ( tokenTypesToReverseIndex == INDEX_ALL )
            {
                return;
            }
            tokenTypesToReverseIndex.add( tokenType );
        }

        /** <summary>
         *  Track the indicated token types in the reverse index. Set
         *  to INDEX_ALL to track all token types.
         *  </summary>
         */
        public void reverseIndex( HashSet<int> tokenTypes )
        {
            tokenTypesToReverseIndex = tokenTypes;
        }

        /** <summary>
         *  Given a node pointer, return its index into the node stream.
         *  This is not its Token stream index.  If there is no reverse map
         *  from node to stream index or the map does not contain entries
         *  for node's token type, a linear search of entire stream is used.
         *  </summary>
         *
         *  <remarks>
         *  Return -1 if exact node pointer not in stream.
         *  </remarks>
         */
        public int getNodeIndex( object node )
        {
            //System.out.println("get "+node);
            if ( tokenTypeToStreamIndexesMap == null )
            {
                return getNodeIndexLinearly( node );
            }
            int tokenType = adaptor.getType( node );
            IList<int> indexes;
            if ( !tokenTypeToStreamIndexesMap.TryGetValue( tokenType, out indexes ) || indexes == null )
            {
                //System.out.println("found linearly; stream index = "+getNodeIndexLinearly(node));
                return getNodeIndexLinearly( node );
            }
            for ( int i = 0; i < indexes.size(); i++ )
            {
                int streamIndex = indexes[i];
                object n = get( streamIndex );
                if ( n == node )
                {
                    //System.out.println("found in index; stream index = "+streamIndexI);
                    return streamIndex; // found it!
                }
            }
            return -1;
        }
#endif

    }
}
