class OverloadedMethod implements MethodAccess {

    @Override
    public Object invokeDynamic(Object object, Object... args) {

        final int length = args.length;


        final List<MethodAccess> methodAccesses = this.methodAccessListByArgNumber.get(length);


        int maxScore = Integer.MIN_VALUE;
        MethodAccess methodAccess = null;

        for (MethodAccess m : methodAccesses) {
            int score = 1;
            final List<TypeType> paramTypeEnumList = m.paramTypeEnumList();

            if (object == null && !m.isStatic()) {
                continue;
            }


            loop:
            for (int argIndex=0; argIndex < args.length; argIndex++) {

                TypeType type =paramTypeEnumList.get(argIndex);
                Object arg = args[argIndex];

                final TypeType instanceType = TypeType.getInstanceType(arg);

                if (instanceType == type) {
                    score += 2_000;
                    continue;
                }

                switch (type){
                    case BYTE_WRAPPER:
                    case BYTE:
                        score = handleByteArg(score, arg, instanceType);
                        break;

                    case SHORT_WRAPPER:
                    case SHORT:
                        score = handleShortArg(score, arg, instanceType);
                        break;

                    case INTEGER_WRAPPER:
                    case INT:
                        score = handleIntArg(score, arg, instanceType);
                        break;


                    case NULL:
                        score--;
                        break;

                    case LONG_WRAPPER:
                    case LONG:
                        score = handleLongArg(score, arg, instanceType);
                        break;

                    case FLOAT_WRAPPER:
                    case FLOAT:
                        score = handleFloatArg(score, arg, instanceType);
                        break;


                    case DOUBLE_WRAPPER:
                    case DOUBLE:
                        score = handleDoubleArg(score, arg, instanceType);
                        break;


                    case CHAR_WRAPPER:
                    case CHAR:
                        if (instanceType == TypeType.CHAR ||
                                instanceType == TypeType.CHAR_WRAPPER) {
                            score+=1000;
                        }
                        break;

                    case STRING:
                        if (instanceType == TypeType.STRING) {
                            score +=1_000;
                        } else if (instanceType == TypeType.CHAR_SEQUENCE
                                || arg instanceof CharSequence) {
                            score +=500;
                        }
                        break;


                    case INSTANCE:
                        if (instanceType == TypeType.INSTANCE) {
                            if (m.parameterTypes()[argIndex].isInstance(arg)){
                                score+=1000;

                            }
                        } else if (instanceType == TypeType.MAP) {
                            score +=1_000;
                        } else if (instanceType == TypeType.LIST) {
                            score +=500;
                        }
                        break;

                    default:
                        if (instanceType == type) {
                            score+=1000;
                        } else {
                            if (m.parameterTypes()[argIndex].isInstance(arg)){
                                score+=1000;

                            }
                        }

                }

            }

            if (score>maxScore) {
                maxScore = score;
                methodAccess = m;
            }
        }

        if (methodAccess!=null) {
            return methodAccess.invokeDynamic(object, args);
        } else {
            /* Place holder for now. */
            List<MethodAccess> varargMethods = this.methodAccessListByArgNumberWithVarArg.get(0);
            if (varargMethods!=null) {
                varargMethods.get(0).invokeDynamic(args);
            }
        }

        return null;
    }

}