/*
 * 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.scr.impl.inject.internal;

import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.felix.scr.impl.helper.Coercions;
import org.osgi.framework.Bundle;
import org.osgi.service.component.ComponentException;

public class Annotations
{
    /** Capture all methods defined by the annotation interface */
    private static final Set<Method> ANNOTATION_METHODS = new HashSet<>();
    static
    {
        for(final Method m : Annotation.class.getMethods())
        {
            ANNOTATION_METHODS.add(m);
        }
    }

    /** Constant for the single element method */
    private static final String VALUE_METHOD = "value";

    /** Constant for the prefix constant. */
    private static final String PREFIX_CONSTANT = "PREFIX_";

    /**
     * Check whether the provided type is a single element annotation.
     * A single element annotation has a method named "value" and all
     * other annotation methods must have a default value.
     * @param clazz The provided type
     * @return {@code true} if the type is a single element annotation.
     */
    static public boolean isSingleElementAnnotation(final Class<?> clazz)
    {
        boolean result = false;
        if ( clazz.isAnnotation() )
        {
            result = true;
            boolean hasValue = false;
            for ( final Method method: clazz.getMethods() )
            {
                // filter out methods from Annotation
                boolean isFromAnnotation = false;
                for(final Method objMethod : ANNOTATION_METHODS)
                {
                    if ( objMethod.getName().equals(method.getName())
                      && Arrays.equals(objMethod.getParameterTypes(), method.getParameterTypes()) )
                    {
                        isFromAnnotation = true;
                        break;
                    }
                }
                if ( isFromAnnotation )
                {
                    continue;
                }
                if ( VALUE_METHOD.equals(method.getName()) )
                {
                    hasValue = true;
                    continue;
                }
                if ( method.getDefaultValue() == null )
                {
                    result = false;
                    break;
                }

            }
            if ( result )
            {
                result = hasValue;
            }

        }
        return result;
    }

    static public String getPrefix(Class<?> clazz)
    {
        try
        {
            final Field f = clazz.getField(PREFIX_CONSTANT);
            if ( Modifier.isStatic(f.getModifiers())
                 && Modifier.isPublic(f.getModifiers())
                 && Modifier.isFinal(f.getModifiers())
                 && String.class.isAssignableFrom(f.getType()))
            {
                final Object value = f.get(null);
                if ( value != null )
                {
                    return value.toString();
                }
            }
        }
        catch ( final Exception ignore)
        {
            // ignore
        }
        return null;
    }

    @SuppressWarnings("unchecked")
	static public <T> T toObject(Class<T> clazz, Map<String, Object> props, Bundle b, boolean supportsInterfaces )
    {
        final boolean isSingleElementAnn = isSingleElementAnnotation(clazz);
        final String prefix = getPrefix(clazz);
        final Map<String, Object> m = new HashMap<>();

        final Map<String, Method> complexFields = new HashMap<>();
        for ( final Method method: clazz.getMethods() )
        {
            final String name = method.getName();
            final String mapped;
            if ( isSingleElementAnn && name.equals(VALUE_METHOD) )
            {
                mapped = mapTypeNameToKey(clazz.getSimpleName());
            }
            else
            {
                mapped = mapIdentifierToKey(name);
            }
            final String key = (prefix == null ? mapped : prefix.concat(mapped));

            Object raw = props.get(key);
            Class<?> returnType = method.getReturnType();
            Object cooked;
            if ( returnType.isInterface() || returnType.isAnnotation())
            {
                complexFields.put(key, method);
                continue;
            }

            try
            {
                if (returnType.isArray())
                {
                    Class<?> componentType = returnType.getComponentType();
                    if (componentType.isInterface() || componentType.isAnnotation())
                    {
                        complexFields.put(key, method);
                        continue;
                    }
                    cooked = coerceToArray(componentType, raw, b);
                }
                else
                {
                    cooked = Coercions.coerce(returnType, raw, b);
                }
            }
            catch (ComponentException e)
            {
                cooked = new Invalid(e);
            }
            m.put( name, cooked );
        }
        if (!complexFields.isEmpty())
        {
            if (supportsInterfaces )
            {
                Map<String, List<Map<String, Object>>> nested = extractSubMaps(complexFields.keySet(), props);
                for (Map.Entry<String, Method> entry: complexFields.entrySet())
                {
                    List<Map<String, Object>> proplist = nested.get(entry.getKey());
                    if (proplist == null)
                    {
                    	proplist = Collections.emptyList();
                    }
                    Method method = entry.getValue();
                    Class<?> returnType  = method.getReturnType();
                    if (returnType.isArray())
                    {
                        Class<?> componentType = returnType.getComponentType();
                        Object result = Array.newInstance(componentType, proplist.size());
                        for (int i = 0; i < proplist.size(); i++)
                        {
                            Map<String, Object> rawElement = proplist.get(i);
                            Object cooked = toObject(componentType, rawElement, b, supportsInterfaces);
                            Array.set(result, i, cooked);
                        }
                        m.put(method.getName(), result);
                    }
                    else
                    {
                        if (!proplist.isEmpty())
                        {
                            Object cooked = toObject(returnType, proplist.get(0), b, supportsInterfaces);
                            m.put(method.getName(), cooked);
                        }
                    }
                }
            }
            else
            {
                for (Method method: complexFields.values())
                {
                    m.put(method.getName(), new Invalid("Invalid annotation member type" + method.getReturnType().getName() + " for member: " + method.getName()));
                }
            }
        }

        final InvocationHandler h = new Handler(m, clazz);
        return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class<?>[] { clazz }, h);
    }

    private static Map<String, List<Map<String, Object>>> extractSubMaps(Collection<String> keys, Map<String, Object> map)
    {
        Map<String, List<Map<String, Object>>> result = new HashMap<>();
        //Form a regexp to recognize all the keys as prefixes in the map keys.
        StringBuilder b = new StringBuilder("(");
        for (String key: keys)
        {
            b.append(key).append("|");
        }
        b.deleteCharAt(b.length() -1);
        b.append(")\\.([0-9]*)\\.(.*)");
        Pattern p = Pattern.compile(b.toString());
        for (Map.Entry<String, Object> entry: map.entrySet())
        {
            String longKey = entry.getKey();
            Matcher m = p.matcher(longKey);
            if (m.matches())
            {
                String key = m.group(1);
                int index = Integer.parseInt(m.group(2));
                String subkey = m.group(3);
                List<Map<String, Object>> subMapsForKey = result.get(key);
                if (subMapsForKey == null)
                {
                    subMapsForKey = new ArrayList<>();
                    result.put(key, subMapsForKey);
                }
                //make sure there is room for the possible new submap
                for (int i = subMapsForKey.size(); i <= index; i++)
                {
                    subMapsForKey.add(new HashMap<String, Object>());
                }
                Map<String, Object> subMap = subMapsForKey.get(index);
                subMap.put(subkey, entry.getValue());
            }
        }
        return result;
    }

    private static Object coerceToArray(Class<?> componentType, Object raw, Bundle bundle)
    {
        if (raw == null)
        {
            return Array.newInstance(componentType, 0);
        }
        if (raw.getClass().isArray())
        {
            int size = Array.getLength(raw);
            Object result = Array.newInstance(componentType, size);
            for (int i = 0; i < size; i++)
            {
                Object rawElement = Array.get(raw, i);
                Object cooked = Coercions.coerce(componentType, rawElement, bundle);
                Array.set(result, i, cooked);
            }
            return result;
        }
        if (raw instanceof Collection)
        {
            @SuppressWarnings("rawtypes")
			Collection raws = (Collection) raw;
            int size = raws.size();
            Object result = Array.newInstance(componentType, size);
            int i = 0;
            for (Object rawElement: raws)
            {
                Object cooked = Coercions.coerce(componentType, rawElement, bundle);
                Array.set(result, i++, cooked);
            }
            return result;

        }
        Object cooked = Coercions.coerce(componentType, raw, bundle);
        Object result = Array.newInstance(componentType, 1);
        Array.set(result, 0, cooked);
        return result;

    }

    private static final Pattern p = Pattern.compile("(\\$_\\$)|(\\$\\$)|(\\$)|(__)|(_)");

    static String mapIdentifierToKey(String name)
    {
        Matcher m = p.matcher(name);
        StringBuffer b = new StringBuffer();
        while (m.find())
        {
            String replacement = "";
            if (m.group(1) != null) replacement = "-";
            if (m.group(2) != null) replacement = "\\$";
            if (m.group(3) != null) replacement = "";
            if (m.group(4) != null) replacement = "_";
            if (m.group(5) != null) replacement = ".";

            m.appendReplacement(b, replacement);
        }
        m.appendTail(b);
        return b.toString();
    }

    static String mapTypeNameToKey(String name)
    {
        final StringBuilder sb = new StringBuilder();
        boolean lastLow = false;
        for(final char c : name.toCharArray())
        {
            if ( lastLow && (Character.isLetter(c) || Character.isDigit(c)) && Character.isUpperCase(c) )
            {
                sb.append('.');
            }
            lastLow = false;
            if ( (Character.isLetter(c) || Character.isDigit(c)) && Character.isLowerCase(c))
            {
                lastLow = true;
            }
            sb.append(Character.toLowerCase(c));
        }
        return sb.toString();
    }

    private final static class Handler implements InvocationHandler
    {
        private final Map<String, Object> values;

        private final Class<?> type;

        public Handler(final Map<String, Object> values, final Class<?> type)
        {
            this.values = values;
            this.type = type;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
        {
            Object value = values.get(method.getName());
            if (value instanceof Invalid)
            {
                throw new ComponentException(((Invalid)value).getMessage());
            }
            if ( value == null )
            {
                // check for methods of the Annotations class like hashCode, toString, equals etc.
                if (method.getName().equals("hashCode") &&
                    method.getParameterTypes().length == 0 )
                {
                    int hashCode = 0;
                    for (final Map.Entry<String, Object> entry : values.entrySet()) {
                        if (value instanceof Invalid) {
                            continue;
                        }
                        hashCode += (127 * entry.getKey().hashCode()) ^ entry.getValue().hashCode();
                    }
                    value = hashCode;
                }
                else if (method.getName().equals("equals")
                         && method.getParameterTypes().length == 1)
                {
                    final Object other = args[0];
                    if (proxy == other)
                    {
                        value = true;
                    }
                    else
                    {
                        value = false;
                        if (type.isInstance(other) && Proxy.isProxyClass(other.getClass()))
                        {
                            final InvocationHandler ih = Proxy.getInvocationHandler(other);
                            if (ih instanceof Handler) {
                                value = ((Handler)ih).values.equals(values);
                            }
                        }
                    }
                }
                else if (method.getName().equals("toString")
                        && method.getParameterTypes().length == 0 )
                {
                    value = type.getName() + " : " + values;
                }
                else if (method.getName().equals("annotationType")
                         && method.getParameterTypes().length == 0 )
                {
                    value = type;
                }
            }
            return value;
        }
    }

    private final static class Invalid
    {
        private final String message;

        public Invalid(ComponentException e)
        {
            this.message = e.getMessage();
        }

        public Invalid(String message)
        {
            this.message = message;
        }

        public String getMessage()
        {
            return message;
        }
    }

}
