/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.felix.gogo.runtime;

import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.felix.service.command.CommandSession;
import org.apache.felix.service.command.Parameter;

public final class Reflective
{
    public final static Object NO_MATCH = new Object();
    public final static String MAIN = "_main";
    public final static Set<String> KEYWORDS = new HashSet<>(
        Arrays.asList(new String[] { "abstract", "continue", "for", "new", "switch",
                "assert", "default", "goto", "package", "synchronized", "boolean", "do",
                "if", "private", "this", "break", "double", "implements", "protected",
                "throw", "byte", "else", "import", "public", "throws", "case", "enum",
                "instanceof", "return", "transient", "catch", "extends", "int", "short",
                "try", "char", "final", "interface", "static", "void", "class",
                "finally", "long", "strictfp", "volatile", "const", "float", "native",
                "super", "while" }));

    /**
     * invokes the named method on the given target using the supplied args,
     * which are converted if necessary.
     * @return the result of the invoked method
     * @throws Exception
     */
    public static Object invoke(CommandSession session, Object target, String name,
        List<Object> args) throws Exception
    {
        Method[] methods = target.getClass().getMethods();
        name = name.toLowerCase();

        String org = name;
        String get = "get" + name;
        String is = "is" + name;
        String set = "set" + name;

        if (KEYWORDS.contains(name))
        {
            name = "_" + name;
        }

        if (target instanceof Class<?>)
        {
            Method[] staticMethods = ((Class<?>) target).getMethods();
            for (Method m : staticMethods)
            {
                String mname = m.getName().toLowerCase();
                if (mname.equals(name) || mname.equals(get) || mname.equals(set)
                    || mname.equals(is) || mname.equals(MAIN))
                {
                    methods = staticMethods;
                    break;
                }
            }
        }

        Method bestMethod = null;
        Object[] bestArgs = null;
        int lowestMatch = Integer.MAX_VALUE;
        ArrayList<Class<?>[]> possibleTypes = new ArrayList<>();

        for (Method m : methods)
        {
            String mname = m.getName().toLowerCase();
            if (mname.equals(name) || mname.equals(get) || mname.equals(set)
                || mname.equals(is) || mname.equals(MAIN))
            {
                Class<?>[] types = m.getParameterTypes();
                ArrayList<Object> xargs = new ArrayList<>(args);

                // pass command name as argv[0] to main, so it can handle
                // multiple commands
                if (mname.equals(MAIN))
                {
                    xargs.add(0, org);
                }

                Object[] parms = new Object[types.length];
                int match = coerce(session, target, m, types, parms, xargs);

                if (match < 0)
                {
                    // coerce failed
                    possibleTypes.add(types);
                }
                else
                {
                    if (match < lowestMatch)
                    {
                        lowestMatch = match;
                        bestMethod = m;
                        bestArgs = parms;
                    }

                    if (match == 0)
                        break; // can't get better score
                }
            }
        }

        if (bestMethod != null)
        {
            bestMethod.setAccessible(true);
            try
            {
                return bestMethod.invoke(target, bestArgs);
            }
            catch (InvocationTargetException e)
            {
                Throwable cause = e.getCause();
                if (cause instanceof Exception)
                {
                    throw (Exception) cause;
                }
                throw e;
            }
        }
        else
        {
            ArrayList<String> list = new ArrayList<>();
            for (Class<?>[] types : possibleTypes)
            {
                StringBuilder buf = new StringBuilder();
                buf.append('(');
                for (Class<?> type : types)
                {
                    if (buf.length() > 1)
                    {
                        buf.append(", ");
                    }
                    buf.append(type.getSimpleName());
                }
                buf.append(')');
                list.add(buf.toString());
            }

            StringBuilder params = new StringBuilder();
            for (Object arg : args)
            {
                if (params.length() > 1)
                {
                    params.append(", ");
                }
                params.append(arg == null ? "null" : arg.getClass().getSimpleName());
            }

            throw new IllegalArgumentException(String.format(
                "Cannot coerce %s(%s) to any of %s", name, params, list));
        }
    }

    /**
     * transform name/value parameters into ordered argument list.
     * params: --param2, value2, --flag1, arg3
     * args: true, value2, arg3
     * @return new ordered list of args.
     */
    private static List<Object> transformParameters(Method method, List<Object> in)
    {
        Annotation[][] pas = method.getParameterAnnotations();
        ArrayList<Object> out = new ArrayList<>();
        ArrayList<Object> parms = new ArrayList<>(in);

        for (Annotation as[] : pas)
        {
            for (Annotation a : as)
            {
                if (a instanceof Parameter)
                {
                    int i = -1;
                    Parameter p = (Parameter) a;
                    for (String name : p.names())
                    {
                        i = parms.indexOf(name);
                        if (i >= 0)
                            break;
                    }

                    if (i >= 0)
                    {
                        // parameter present
                        parms.remove(i);
                        Object value = p.presentValue();
                        if (Parameter.UNSPECIFIED.equals(value))
                        {
                            if (i >= parms.size())
                                return null; // missing parameter, so try other methods
                            value = parms.remove(i);
                        }
                        out.add(value);
                    }
                    else
                    {
                        out.add(p.absentValue());
                    }

                }
            }
        }

        out.addAll(parms);

        return out;
    }

    /**
     * Complex routein to convert the arguments given from the command line to
     * the arguments of the method call. First, an attempt is made to convert
     * each argument. If this fails, a check is made to see if varargs can be
     * applied. This happens when the last method argument is an array.
     * @return -1 if arguments can't be coerced; 0 if no coercion was necessary;
     *          > 0 if coercion was needed.
     */
    private static int coerce(CommandSession session, Object target, Method m,
        Class<?> types[], Object out[], List<Object> in)
    {
        in = transformParameters(m, in);
        if (in == null)
        {
            // missing parameter argument?
            return -1;
        }

        int[] convert = { 0 };

        // Check if the command takes a session
        if ((types.length > 0) && types[0].isInterface()
            && types[0].isAssignableFrom(session.getClass()))
        {
            in.add(0, session);
        }

        int i = 0;
        while (i < out.length)
        {
            out[i] = null;

            // Try to convert one argument
            if (in.size() == 0 || i == types.length - 1 && types[i].isArray() && in.size() > 1)
            {
                out[i] = NO_MATCH;
            }
            else
            {
                out[i] = coerce(session, types[i], in.get(0), convert);

                if (out[i] == null && types[i].isArray() && in.size() > 0)
                {
                    // don't coerce null to array FELIX-2432
                    out[i] = NO_MATCH;
                }

                if (out[i] != NO_MATCH)
                {
                    in.remove(0);
                }
            }

            if (out[i] == NO_MATCH)
            {
                // No match, check for varargs
                if (types[i].isArray() && (i == types.length - 1))
                {
                    // Try to parse the remaining arguments in an array
                    Class<?> ctype = types[i].getComponentType();
                    int asize = in.size();
                    Object array = Array.newInstance(ctype, asize);
                    int n = i;
                    while (in.size() > 0)
                    {
                        Object t = coerce(session, ctype, in.remove(0), convert);
                        if (t == NO_MATCH)
                        {
                            return -1;
                        }
                        Array.set(array, i - n, t);
                        i++;
                    }
                    out[n] = array;

                    /*
                     * 1. prefer f() to f(T[]) with empty array
                     * 2. prefer f(T) to f(T[1])
                     * 3. prefer f(T) to f(Object[1]) even if there is a conversion cost for T
                     * 
                     * 1 & 2 require to add 1 to conversion cost, but 3 also needs to match
                     * the conversion cost for T.
                     */
                    return convert[0] + 1 + (asize * 2);
                }
                return -1;
            }
            i++;
        }

        if (in.isEmpty())
            return convert[0];
        return -1;
    }

    /**
     * converts given argument to specified type and increments convert[0] if any conversion was needed.
     * @param convert convert[0] is incremented according to the conversion needed,
     * to allow the "best" conversion to be determined.
     * @return converted arg or NO_MATCH if no conversion possible.
     */
    public static Object coerce(CommandSession session, Class<?> type, Object arg,
        int[] convert)
    {
        if (arg == null)
        {
            return null;
        }

        if (type.isAssignableFrom(arg.getClass()))
        {
            return arg;
        }

        if (type.isArray())
        {
            return NO_MATCH;
        }

        if (type.isPrimitive() && arg instanceof Long)
        {
            // no-cost conversions between integer types
            Number num = (Number) arg;

            if (type == short.class)
            {
                return num.shortValue();
            }
            if (type == int.class)
            {
                return num.intValue();
            }
            if (type == long.class)
            {
                return num.longValue();
            }
        }

        // all following conversions cost 2 points
        convert[0] += 2;

        Object converted = ((CommandSessionImpl) session).doConvert(type, arg);
        if (converted != null)
        {
            return converted;
        }

        String string = toString(arg);

        if (type.isAssignableFrom(String.class))
        {
            return string;
        }

        if (type.isEnum())
        {
            for (Object o : type.getEnumConstants())
            {
                if (o.toString().equalsIgnoreCase(string))
                {
                    return o;
                }
            }
        }

        if (type.isPrimitive())
        {
            type = primitiveToObject(type);
        }

        try
        {
            return type.getConstructor(String.class).newInstance(string);
        }
        catch (Exception e)
        {
        }

        if (type == Character.class && string.length() == 1)
        {
            return string.charAt(0);
        }

        return NO_MATCH;
    }

    private static String toString(Object arg)
    {
        if (arg instanceof Map)
        {
            StringBuilder sb = new StringBuilder();
            sb.append("[");
            boolean first = true;
            for (Map.Entry<?,?> entry : ((Map<?,?>) arg).entrySet())
            {
                if (!first) {
                    sb.append(" ");
                }
                first = false;
                writeValue(sb, entry.getKey());
                sb.append("=");
                writeValue(sb, entry.getValue());
            }
            sb.append("]");
            return sb.toString();
        }
        else if (arg instanceof Collection)
        {
            StringBuilder sb = new StringBuilder();
            sb.append("[");
            boolean first = true;
            for (Object o : ((Collection) arg))
            {
                if (!first) {
                    sb.append(" ");
                }
                first = false;
                writeValue(sb, o);
            }
            sb.append("]");
            return sb.toString();
        }
        else
        {
            return arg.toString();
        }
    }

    private static void writeValue(StringBuilder sb, Object o) {
        if (o == null || o instanceof Boolean || o instanceof Number)
        {
            sb.append(o);
        }
        else
        {
            String s = o.toString();
            sb.append("\"");
            for (int i = 0; i < s.length(); i++)
            {
                char c = s.charAt(i);
                if (c == '\"' || c == '=')
                {
                    sb.append("\\");
                }
                sb.append(c);
            }
            sb.append("\"");
        }
    }

    private static Class<?> primitiveToObject(Class<?> type)
    {
        if (type == boolean.class)
        {
            return Boolean.class;
        }
        if (type == byte.class)
        {
            return Byte.class;
        }
        if (type == char.class)
        {
            return Character.class;
        }
        if (type == short.class)
        {
            return Short.class;
        }
        if (type == int.class)
        {
            return Integer.class;
        }
        if (type == float.class)
        {
            return Float.class;
        }
        if (type == double.class)
        {
            return Double.class;
        }
        if (type == long.class)
        {
            return Long.class;
        }
        return null;
    }

}
