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

namespace edu.neu.ccs.demeterf{
    public class TP : ID{
        Object combine(Object o) { return o; }
        Object combine(Object o, Object o1) { return help(o,new Object[]{o1}); }
        Object combine(Object o, Object o1, Object o2) { return help(o, new Object[] { o1,o2 }); }
        Object combine(Object o, Object o1, Object o2, Object o3) { return help(o, new Object[] { o1,o2,o3 }); }
        Object combine(Object o, Object o1, Object o2, Object o3, Object o4) { return help(o, new Object[] { o1,o2,o3,o4 }); }
        Object combine(Object o, Object o1, Object o2, Object o3, Object o4, Object o5) { return help(o, new Object[] { o1,o2,o3,o4,o5 }); }
        Object combine(Object o, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6) { return help(o, new Object[] { o1,o2,o3,o4,o5,o6 }); }
        Object combine(Object o, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7) { return help(o, new Object[] { o1,o2,o3,o4,o5,o6,o7 }); }
        Object combine(Object o, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8) { return help(o, new Object[] { o1,o2,o3,o4,o5,o6,o7,o8 }); }
        Object combine(Object o, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9) { return help(o, new Object[] { o1,o2,o3,o4,o5,o6,o7,o8,o9 }); }



        Object help(Object host, Object[] fields) {
            Type t = host.GetType();
            int nfs = Util.getFuncFields(t).length();
            if(nfs == 0 || Util.isBuiltIn(t))return host;
            if(nfs > fields.Length)
                nfs = fields.Length;

            MethodDB<ConstructorInfo> db = MethodDB<ConstructorInfo>.createCDB(t);
            Type[] ts = Util.typesFromObjects(fields,nfs);
            DBEntry<ConstructorInfo> con = db.matchEntry(ts);
            if(con == null) {
                throw new Exception("\n ** Bc Error: Did Not Find One of: \n    "+
                    Util.signature(t, "<init>", ts, ts.Length-1)+" OR\n    "+
                    Util.signature(t, "<init>", ts, ts.Length));
            }
            return con.getMethod().Invoke(Util.objectSubset(fields, con.numArgs()));
        }
    }
}