private static int SelectBest(TypeReferences typeRefs, MemberInfo[] match, int matches, IReflect[] argIRs, ParameterInfo[][] fparams, object[][] aparams, int candidates, int parameters)
{
if (candidates == 0)
{
return -1;
}
if (candidates == 1)
{
for (int m = 0; m < matches; m++)
{
if (fparams[m] != null)
{
return m;
}
}
}
bool[] flagArray = new bool[matches];
int[] numArray = new int[matches];
for (int i = 0; i < matches; i++)
{
ParameterInfo[] infoArray = fparams[i];
if (infoArray != null)
{
int length = infoArray.Length;
int num4 = (argIRs == null) ? aparams[i].Length : argIRs.Length;
if ((num4 > length) && ((length == 0) || !Microsoft.JScript.CustomAttribute.IsDefined(infoArray[length - 1], typeof(ParamArrayAttribute), false)))
{
fparams[i] = null;
candidates--;
}
else
{
for (int n = parameters; n < length; n++)
{
ParameterInfo target = infoArray[n];
if ((n == (length - 1)) && Microsoft.JScript.CustomAttribute.IsDefined(target, typeof(ParamArrayAttribute), false))
{
break;
}
if (TypeReferences.GetDefaultParameterValue(target) is DBNull)
{
numArray[i] = 50;
}
}
}
}
}
for (int j = 0; candidates > 1; j++)
{
int num7 = 0;
int num8 = 0x7fffffff;
bool flag = false;
for (int num9 = 0; num9 < matches; num9++)
{
int num10 = 0;
ParameterInfo[] infoArray2 = fparams[num9];
if (infoArray2 != null)
{
IReflect missing = typeRefs.Missing;
if (argIRs == null)
{
if (aparams[num9].Length > j)
{
object obj3 = aparams[num9][j];
if (obj3 == null)
{
obj3 = DBNull.Value;
}
missing = typeRefs.ToReferenceContext(obj3.GetType());
}
}
else if (j < parameters)
{
missing = argIRs[j];
}
int num11 = infoArray2.Length;
if ((num11 - 1) > j)
{
num7++;
}
IReflect formal = typeRefs.Missing;
if ((((num11 > 0) && (j >= (num11 - 1))) && (Microsoft.JScript.CustomAttribute.IsDefined(infoArray2[num11 - 1], typeof(ParamArrayAttribute), false) && !(missing is TypedArray))) && ((missing != typeRefs.ArrayObject) && (!(missing is Type) || !((Type) missing).IsArray)))
{
ParameterInfo info2 = infoArray2[num11 - 1];
if (info2 is ParameterDeclaration)
{
formal = ((TypedArray) ((ParameterDeclaration) info2).ParameterIReflect).elementType;
}
else
{
formal = info2.ParameterType.GetElementType();
}
if (j == (num11 - 1))
{
numArray[num9]++;
}
}
else if (j < num11)
{
ParameterInfo parameter = infoArray2[j];
formal = (parameter is ParameterDeclaration) ? ((ParameterDeclaration) parameter).ParameterIReflect : parameter.ParameterType;
if ((missing == typeRefs.Missing) && !(TypeReferences.GetDefaultParameterValue(parameter) is DBNull))
{
missing = formal;
num10 = 1;
}
}
int num12 = (TypeDistance(typeRefs, formal, missing) + numArray[num9]) + num10;
if (num12 == num8)
{
if ((j == (num11 - 1)) && flagArray[num9])
{
candidates--;
fparams[num9] = null;
}
flag = flag && flagArray[num9];
}
else if (num12 > num8)
{
if ((flag && (j < num11)) && FormalParamTypeIsObject(fparams[num9][j]))
{
num8 = num12;
}
else if (((j <= (num11 - 1)) || (missing != typeRefs.Missing)) || !Microsoft.JScript.CustomAttribute.IsDefined(infoArray2[num11 - 1], typeof(ParamArrayAttribute), false))
{
flagArray[num9] = true;
}
}
else
{
if ((candidates == 1) && !flagArray[num9])
{
return num9;
}
flag = flagArray[num9];
for (int num13 = 0; num13 < num9; num13++)
{
if ((fparams[num13] != null) && !flagArray[num13])
{
bool flag2 = fparams[num13].Length <= j;
if ((!flag2 || (parameters > j)) && ((flag2 || !flag) || !FormalParamTypeIsObject(fparams[num13][j])))
{
flagArray[num13] = true;
}
}
}
num8 = num12;
}
}
}
if ((j >= (parameters - 1)) && (num7 < 1))
{
break;
}
}
int index = -1;
for (int k = 0; (k < matches) && (candidates > 0); k++)
{
ParameterInfo[] suppars = fparams[k];
if (suppars != null)
{
if (flagArray[k])
{
candidates--;
fparams[k] = null;
}
else if (index == -1)
{
index = k;
}
else if (Class.ParametersMatch(suppars, fparams[index]))
{
MemberInfo info4 = match[index];
JSWrappedMethod method = match[index] as JSWrappedMethod;
if (method != null)
{
info4 = method.method;
}
if (((info4 is JSFieldMethod) || (info4 is JSConstructor)) || (info4 is JSProperty))
{
candidates--;
fparams[k] = null;
}
else
{
Type declaringType = match[index].DeclaringType;
Type c = match[k].DeclaringType;
if (declaringType != c)
{
if (c.IsAssignableFrom(declaringType))
{
candidates--;
fparams[k] = null;
}
else if (declaringType.IsAssignableFrom(c))
{
fparams[index] = null;
index = k;
candidates--;
}
}
}
}
}
}
if (candidates != 1)
{
throw new AmbiguousMatchException();
}
return index;
}