using System;
using System.Reflection;
using edu.neu.ccs.demeterf.control;
using edu.neu.ccs.demeterf.dispatch;
using edu.neu.ccs.demeterf.util;

namespace edu.neu.ccs.demeterf{
    public class Traversal : AbstTraversal{
        protected FC func;
        protected MethodDB<MethodInfo> buildDB;
        protected MethodDB<MethodInfo> augDB;

        // Create a parameterized Traversal that goes Everywhere

        public Traversal(FC f) : this(f, Control.everywhere()){}
        
        // Create a Traversal with Selective edge/field Bypassing

        public Traversal(FC f, Control c) : base(c){
            func = f;
            buildDB = MethodDB<MethodInfo>.createMDB(f.GetType(), FC.buildMethodName);
            augDB = MethodDB<MethodInfo>.createMDB(f.GetType(), FC.augMethodName);
        }
        
        public static Traversal onestep(FC f){ return new Traversal(f, Control.nowhere()); }
        
        // Apply the Builder to this list of 'Fields'

        protected override Object applyBuilder(Object[] o, bool leaf)
        { return Util.applyFObj(func, o, buildDB, FC.buildMethodName, (leaf?0:-1)); }


        // Apply the Augmentor the the Argument at this Object

        protected override Object applyAugment(Object[] o, Type pt, String fn){
            Object field = new Fields.any();
            if(pt != null){
                // Look for a class that represents the field

                Assembly a = pt.Assembly;
                String fName = pt.FullName+"+"+fn+"F";
                try{
                    Type fc = a.GetType(fName,true);
                    ConstructorInfo con = fc.GetConstructor(new Type[0]);
                    field = con.Invoke(new Object[0]);
                }catch(Exception e){
                    //Util.println("Looking for: "+fName);

                    //Util.println(" Field Class Not Found: "+fName+"\n   Exception: "+e.Message);

                }
            }
            return Util.applyFObj(func, new Object[]{o[0],field,o[1]},augDB, FC.buildMethodName, 2);
        }
    }
}