/*
 * 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.schematizer.impl;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.apache.felix.schematizer.AsDTO;
import org.apache.felix.schematizer.Node.CollectionType;
import org.osgi.util.converter.TypeReference;

public class Util {
    private static final Map<Class<?>, Class<?>> boxedClasses;
    static {
        Map<Class<?>, Class<?>> m = new HashMap<>();
        m.put(int.class, Integer.class);
        m.put(long.class, Long.class);
        m.put(double.class, Double.class);
        m.put(float.class, Float.class);
        m.put(boolean.class, Boolean.class);
        m.put(char.class, Character.class);
        m.put(byte.class, Byte.class);
        m.put(void.class, Void.class);
        m.put(short.class, Short.class);
        boxedClasses = Collections.unmodifiableMap(m);
    }

    public static Type primitiveToBoxed(Type type) {
        if (type instanceof Class)
            return primitiveToBoxed((Class<?>) type);
        else
            return null;
    }

    public static Class<?> primitiveToBoxed(Class<?> cls) {
        Class<?> boxed = boxedClasses.get(cls);
        if (boxed != null)
            return boxed;
        else
            return cls;
    }

    public static byte [] readStream(InputStream is) throws IOException {
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] bytes = new byte[8192];

            int length = 0;
            int offset = 0;

            while ((length = is.read(bytes, offset, bytes.length - offset)) != -1) {
                offset += length;

                if (offset == bytes.length) {
                    baos.write(bytes, 0, bytes.length);
                    offset = 0;
                }
            }
            if (offset != 0) {
                baos.write(bytes, 0, offset);
            }
            return baos.toByteArray();
        } finally {
            is.close();
        }
    }

    public static Class<?> rawClassOf(Object type) {
        Class<?> rawClass = null;
        if (type instanceof Class) {
            rawClass = (Class<?>)type;
        } else if (type instanceof ParameterizedType) {
            ParameterizedType paramType = (ParameterizedType) type;
            Type rawType = paramType.getRawType();
            if (rawType instanceof Class)
                rawClass = (Class<?>)rawType;
        } else if (type instanceof TypeReference) {
            return rawClassOf(((TypeReference<?>)type).getType());
        }

        return rawClass;
    }

    public static TypeReference<?> typeReferenceOf(Object type) {
        TypeReference<?> typeRef = null;
        if (type instanceof TypeReference)
            typeRef = (TypeReference<?>)type;
        return typeRef;
    }

    public static boolean isDTOType(Class<?> cls) {
        try {
            cls.getDeclaredConstructor();
        } catch (NoSuchMethodException | SecurityException e) {
            // No zero-arg constructor, not a DTO
            return false;
        }

        // ATTENTION!! (Note from David Leangen)
        // This may not be according to spec, but without this, it is not possible
        // to use streams in the constructor, which I think is not intended.
        if (cls.getDeclaredMethods().length > 0) {
            return Arrays.stream(cls.getDeclaredMethods())
                    .map(m -> m.getName())
                    .allMatch(n -> n.startsWith( "lambda$"));
        }

        for (Method m : cls.getMethods()) {
            try {
                Object.class.getMethod(m.getName(), m.getParameterTypes());
            } catch (NoSuchMethodException snme) {
                // Not a method defined by Object.class (or override of such method)
                return false;
            }
        }

        for (Field f : cls.getDeclaredFields()) {
            int modifiers = f.getModifiers();
            if (Modifier.isStatic(modifiers)) {
                // ignore static fields
                continue;
            }

            if (!Modifier.isPublic(modifiers)) {
                return false;
            }
        }

        for (Field f : cls.getFields()) {
            int modifiers = f.getModifiers();
            if (Modifier.isStatic(modifiers)) {
                // ignore static fields
                continue;
            }

            if (!Modifier.isPublic(modifiers)) {
                return false;
            }
        }
        return true;
    }

    public static boolean hasDTOAnnotation(Class<?> clazz) {
        AsDTO asDTOAnnotation = clazz.getAnnotation(AsDTO.class);
        return asDTOAnnotation != null;
    }

    public static boolean asDTO(Class<?> clazz) {
        return hasDTOAnnotation(clazz) || isDTOType(clazz);
    }

    public static boolean hasCollectionTypeAnnotation(Field field) {
        if (field == null)
            return false;

        Annotation[] annotations = field.getAnnotations();
        if (annotations.length == 0)
            return false;

        return Arrays.stream(annotations)
            .map(a -> a.annotationType().getName())
            .anyMatch(a -> "CollectionType".equals(a.substring(a.lastIndexOf(".") + 1) ));
    }

    public static Class<?> collectionTypeOf(Field field) {
        Annotation[] annotations = field.getAnnotations();

        Annotation annotation = Arrays.stream(annotations)
            .filter(a -> "CollectionType".equals(a.annotationType().getName().substring(a.annotationType().getName().lastIndexOf(".") + 1) ))
            .findFirst()
            .get();

        try {
            Method m = annotation.annotationType().getMethod("value");
            Class<?> value = (Class<?>)m.invoke(annotation, (Object[])null);
            return value;            
        } catch ( Exception e ) {
            return null;
        }
    }

    public static Class<?> getCollectionTypeOf(Field field) {
        Class<?> collectionType;
        CollectionType collectionTypeAnnotation = field.getAnnotation(CollectionType.class);
        if (collectionTypeAnnotation != null)
            collectionType = collectionTypeAnnotation.value();
        else if (hasCollectionTypeAnnotation(field))
            collectionType = collectionTypeOf(field);
        else
            collectionType = Object.class;

        return collectionType;
    }

    public static boolean isCollectionType(Class<?> clazz) {
        return Collection.class.isAssignableFrom(clazz);        
    }

    public static Map<String, NodeImpl> extractChildren(String path, Map<String, NodeImpl> allNodes) {
        final Map<String, NodeImpl> children = new HashMap<>();
        for (String key : allNodes.keySet()) {
            String newKey = key.replaceFirst(path, "");
            if (!newKey.substring(1).contains("/"))
                children.put( newKey, allNodes.get(key));
        }

        return children;
    }
}
