// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package io.v.v23.vdl;

import com.google.common.base.Joiner;
import com.google.common.base.Strings;

import java.lang.reflect.*;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;

import io.v.v23.security.BlessingPattern;
import io.v.v23.security.BlessingPatternNativeConverter;
import io.v.v23.security.Blessings;
import io.v.v23.security.BlessingsNativeConverter;
import io.v.v23.security.Discharge;
import io.v.v23.security.DischargeNativeConverter;
import io.v.v23.security.access.AccessList;
import io.v.v23.security.access.AccessListNativeConverter;
import io.v.v23.vdl.NativeTime.DateTimeConverter;
import io.v.v23.vdl.NativeTime.DurationConverter;
import io.v.v23.vdl.NativeTypes.Converter;
import io.v.v23.vdl.VdlType.Builder;
import io.v.v23.vdl.VdlType.PendingType;
import io.v.v23.verror.VException;
import io.v.v23.verror.VExceptionVdlConverter;

/**
 * Types provides helpers to create VDL types.
 */
public final class Types {
    /**
     * The {@code VdlType} object representing the VDL type any, it is unnamed.
     */
    public static final VdlType ANY = createPrimitiveType(Kind.ANY);

    /**
     * The {@code VdlType} object representing the VDL type bool, it is unnamed.
     */
    public static final VdlType BOOL = createPrimitiveType(Kind.BOOL);

    /**
     * The {@code VdlType} object representing the VDL type byte, it is unnamed.
     */
    public static final VdlType BYTE = createPrimitiveType(Kind.BYTE);

    /**
     * The {@code VdlType} object representing the VDL type uint16, it is unnamed.
     */
    public static final VdlType UINT16 = createPrimitiveType(Kind.UINT16);

    /**
     * The {@code VdlType} object representing the VDL type uint32, it is unnamed.
     */
    public static final VdlType UINT32 = createPrimitiveType(Kind.UINT32);

    /**
     * The {@code VdlType} object representing the VDL type uint64, it is unnamed.
     */
    public static final VdlType UINT64 = createPrimitiveType(Kind.UINT64);

    /**
     * The {@code VdlType} object representing the VDL type int16, it is unnamed.
     */
    public static final VdlType INT16 = createPrimitiveType(Kind.INT16);

    /**
     * The {@code VdlType} object representing the VDL type int32, it is unnamed.
     */
    public static final VdlType INT32 = createPrimitiveType(Kind.INT32);

    /**
     * The {@code VdlType} object representing the VDL type int64, it is unnamed.
     */
    public static final VdlType INT64 = createPrimitiveType(Kind.INT64);

    /**
     * The {@code VdlType} object representing the VDL type float32, it is unnamed.
     */
    public static final VdlType FLOAT32 = createPrimitiveType(Kind.FLOAT32);

    /**
     * The {@code VdlType} object representing the VDL type float64, it is unnamed.
     */
    public static final VdlType FLOAT64 = createPrimitiveType(Kind.FLOAT64);

    /**
     * The {@code VdlType} object representing the VDL type complex64, it is unnamed.
     */
    public static final VdlType COMPLEX64 = createPrimitiveType(Kind.COMPLEX64);

    /**
     * The {@code VdlType} object representing the VDL type complex128, it is unnamed.
     */
    public static final VdlType COMPLEX128 = createPrimitiveType(Kind.COMPLEX128);

    /**
     * The {@code VdlType} object representing the VDL type string, it is unnamed.
     */
    public static final VdlType STRING = createPrimitiveType(Kind.STRING);

    /**
     * The {@code VdlType} object representing the VDL type typeObject, it is unnamed.
     */
    public static final VdlType TYPEOBJECT = createPrimitiveType(Kind.TYPEOBJECT);

    private static final Map<Type, VdlType> typeCache = new ConcurrentHashMap<Type, VdlType>();
    private static final Map<VdlType, Type> typeRegistry = new ConcurrentHashMap<VdlType, Type>();
    private static final Map<Type, Converter> nativeTypeRegistry =
            new ConcurrentHashMap<Type, Converter>();

    static {
        typeCache.put(VdlAny.class, ANY);
        typeCache.put(VdlBool.class, BOOL);
        typeCache.put(VdlByte.class, BYTE);
        typeCache.put(VdlUint16.class, UINT16);
        typeCache.put(VdlUint32.class, UINT32);
        typeCache.put(VdlUint64.class, UINT64);
        typeCache.put(VdlInt16.class, INT16);
        typeCache.put(VdlInt32.class, INT32);
        typeCache.put(VdlInt64.class, INT64);
        typeCache.put(VdlFloat32.class, FLOAT32);
        typeCache.put(VdlFloat64.class, FLOAT64);
        typeCache.put(VdlComplex64.class, COMPLEX64);
        typeCache.put(VdlComplex128.class, COMPLEX128);
        typeCache.put(VdlString.class, STRING);
        typeCache.put(VdlTypeObject.class, TYPEOBJECT);

        typeCache.put(Boolean.TYPE, BOOL);
        typeCache.put(Boolean.class, BOOL);
        typeCache.put(Byte.TYPE, BYTE);
        typeCache.put(Byte.class, BYTE);
        typeCache.put(Short.TYPE, INT16);
        typeCache.put(Short.class, INT16);
        typeCache.put(Integer.TYPE, INT32);
        typeCache.put(Integer.class, INT32);
        typeCache.put(Long.TYPE, INT64);
        typeCache.put(Long.class, INT64);
        typeCache.put(Float.TYPE, FLOAT32);
        typeCache.put(Float.class, FLOAT32);
        typeCache.put(Double.TYPE, FLOAT64);
        typeCache.put(Double.class, FLOAT64);
        typeCache.put(String.class, STRING);

        // When registering native types, make sure to register "child" types first. For example,
        // if VDL type A contains VDL type B and both have native types that you want to register
        // here, you must register A before B.
        registerNativeType(VException.class, VExceptionVdlConverter.INSTANCE);
        registerNativeType(org.joda.time.DateTime.class, DateTimeConverter.INSTANCE);
        registerNativeType(org.joda.time.Duration.class, DurationConverter.INSTANCE);
        registerNativeType(Discharge.class, DischargeNativeConverter.INSTANCE);
        registerNativeType(Blessings.class, BlessingsNativeConverter.INSTANCE);
        registerNativeType(BlessingPattern.class, BlessingPatternNativeConverter.INSTANCE);
        registerNativeType(AccessList.class, AccessListNativeConverter.INSTANCE);
    }

    private static void registerNativeType(Type nativeType, Converter converter) {
        VdlType vdlType = getVdlTypeFromReflect(converter.getWireType());
        typeCache.put(nativeType, vdlType);
        typeRegistry.put(vdlType, nativeType);
        nativeTypeRegistry.put(nativeType, converter);
    }

    private static VdlType createPrimitiveType(Kind kind) {
        Builder builder = new Builder();
        PendingType pending = builder.newPending(kind);
        builder.build();
        return pending.built();
    }

    /**
     * Returns a {@code VdlType} object representing a VDL type of specified kind.
     */
    public static VdlType primitiveTypeFromKind(Kind kind) {
        switch (kind) {
            case ANY:
                return ANY;
            case BOOL:
                return BOOL;
            case BYTE:
                return BYTE;
            case UINT16:
                return UINT16;
            case UINT32:
                return UINT32;
            case UINT64:
                return UINT64;
            case INT16:
                return INT16;
            case INT32:
                return INT32;
            case INT64:
                return INT64;
            case FLOAT32:
                return FLOAT32;
            case FLOAT64:
                return FLOAT64;
            case COMPLEX64:
                return COMPLEX64;
            case COMPLEX128:
                return COMPLEX128;
            case STRING:
                return STRING;
            case TYPEOBJECT:
                return TYPEOBJECT;
            default:
                throw new RuntimeException("Unknown primitive kind " + kind);
        }
    }

    /**
     * A helper used to create a single VDL enum type.
     */
    public static VdlType enumOf(String... labels) {
        Builder builder = new Builder();
        PendingType pending = builder.newPending(Kind.ENUM);
        for (String label : labels) {
            pending.addLabel(label);
        }
        builder.build();
        return pending.built();
    }

    /**
     * A helper used to create a single VDL fixed length array type.
     */
    public static VdlType arrayOf(int len, VdlType elem) {
        Builder builder = new Builder();
        PendingType pending = builder.newPending(Kind.ARRAY).setLength(len).setElem(elem);
        builder.build();
        return pending.built();
    }

    /**
     * A helper used to create a single VDL list type.
     */
    public static VdlType listOf(VdlType elem) {
        Builder builder = new Builder();
        PendingType pending = builder.newPending(Kind.LIST).setElem(elem);
        builder.build();
        return pending.built();
    }

    /**
     * A helper used to create a single VDL set type.
     */
    public static VdlType setOf(VdlType key) {
        Builder builder = new Builder();
        PendingType pending = builder.newPending(Kind.SET).setKey(key);
        builder.build();
        return pending.built();
    }

    /**
     * A helper used to create a single VDL map type.
     */
    public static VdlType mapOf(VdlType key, VdlType elem) {
        Builder builder = new Builder();
        PendingType pending = builder.newPending(Kind.MAP).setKey(key).setElem(elem);
        builder.build();
        return pending.built();
    }

    /**
     * A helper used to create a single VDL struct type.
     */
    public static VdlType structOf(VdlField... fields) {
        Builder builder = new Builder();
        PendingType pending = builder.newPending(Kind.STRUCT);
        for (VdlField field : fields) {
            pending.addField(field.getName(), field.getType());
        }
        builder.build();
        return pending.built();
    }

    /**
     * A helper used to create a single VDL union type.
     */
    public static VdlType unionOf(VdlField... fields) {
        Builder builder = new Builder();
        PendingType pending = builder.newPending(Kind.UNION);
        for (VdlField field : fields) {
            pending.addField(field.getName(), field.getType());
        }
        builder.build();
        return pending.built();
    }

    /**
     * A helper used to create a single VDL optional type.
     */
    public static VdlType optionalOf(VdlType elem) {
        Builder builder = new Builder();
        PendingType pending = builder.newPending(Kind.OPTIONAL).setElem(elem);
        builder.build();
        return pending.built();
    }

    /**
     * A helper used to create a single named VDL type based on another VDL type.
     */
    public static VdlType named(String name, VdlType base) {
        Builder builder = new Builder();
        PendingType pending = builder.newPending().assignBase(base).setName(name);
        builder.build();
        return pending.built();
    }

    /**
     * Returns a {@code NativeTypes.Converter} object for a provided java native type or null
     * if there is no converter from provided java type to its VDL wire representation.
     */
    public static NativeTypes.Converter getNativeTypeConverter(Type type) {
        return nativeTypeRegistry.get(type);
    }

    /**
     * Creates a {@code VdlType} object corresponding to a {@code java.lang.reflect.Type} object.
     * Resolves maps, sets, lists, arrays, primitives and classes generated from *.vdl files.
     * All results are statically cached. All named VDL types are also registered so that the
     * corresponding {@code Type} object can be retrieved by calling {@code getReflectTypeForVdl}.
     *
     * @throws IllegalArgumentException if the VDL type can't be constructed
     */
    public static VdlType getVdlTypeFromReflect(Type type) {
        if (typeCache.containsKey(type)) {
            return typeCache.get(type);
        }
        return synchronizedLookupOrBuildType(type);
    }

    /**
     * Returns a {@code Type} object corresponding to VDL type.
     * We look up named types that were built by calling {@code getVdlTypeFromReflect}, and build
     * the unnamed types that have java native equivalent (all except array, enum, struct, union).
     *
     * @param vdlType the VDL type
     * @return the {@code Type} object
     * @throws IllegalArgumentException if the type can't be constructed
     */
    public static Type getReflectTypeForVdl(VdlType vdlType) {
        Type type = typeRegistry.get(vdlType);
        if (type != null) {
            return type;
        }
        if (!Strings.isNullOrEmpty(vdlType.getName())) {  // named type
            throw new IllegalArgumentException("Can't build java type for VDL type " + vdlType + " - named type is unregistered");
        }

        Type key, elem;
        switch (vdlType.getKind()) {
            case ARRAY:
            case ENUM:
            case STRUCT:
            case UNION:
                throw new IllegalArgumentException("Can't build java type for VDL type " + vdlType + " - illegal unnamed union");
            case ANY:
                return VdlAny.class;
            case BOOL:
                return Boolean.class;
            case BYTE:
                return Byte.class;
            case COMPLEX128:
                return VdlComplex128.class;
            case COMPLEX64:
                return VdlComplex64.class;
            case FLOAT32:
                return Float.class;
            case FLOAT64:
                return Double.class;
            case INT16:
                return Short.class;
            case INT32:
                return Integer.class;
            case INT64:
                return Long.class;
            case LIST:
                if (vdlType.getElem().getKind() == Kind.BYTE) {
                  return byte[].class;
                }
                elem = getReflectTypeForVdl(vdlType.getElem());
                if (elem != null) {
                    return new ParameterizedTypeImpl(VdlList.class, elem);
                }
                throw new IllegalArgumentException("Can't build java type for VDL type " + vdlType + " - unknown list elem type");
            case MAP:
                key = getReflectTypeForVdl(vdlType.getKey());
                elem = getReflectTypeForVdl(vdlType.getElem());
                if (key != null && elem != null) {
                    return new ParameterizedTypeImpl(VdlMap.class, key, elem);
                }
                throw new IllegalArgumentException("Can't build java type for VDL type " + vdlType + " - unknown map key or elem type");
            case OPTIONAL:
                elem = getReflectTypeForVdl(vdlType.getElem());
                if (elem != null) {
                    return new ParameterizedTypeImpl(VdlOptional.class, elem);
                }
                throw new IllegalArgumentException("Can't build java type for VDL type " + vdlType + " - unkown optional elem type");
            case SET:
                key = getReflectTypeForVdl(vdlType.getKey());
                if (key != null) {
                    return new ParameterizedTypeImpl(VdlSet.class, key);
                }
                throw new IllegalArgumentException("Can't build java type for VDL type " + vdlType + " - unknown set key type");
            case STRING:
                return String.class;
            case TYPEOBJECT:
                return VdlTypeObject.class;
            case UINT16:
                return VdlUint16.class;
            case UINT32:
                return VdlUint32.class;
            case UINT64:
                return VdlUint64.class;
            default:
                throw new IllegalArgumentException("Unsupported VDL type: " + vdlType);
        }
    }

    /**
     * Tries to load a Java class that was generated from named VDL type.
     *
     * @param name the name of VDL type
     * @return true iff the class was found
     */
    public static boolean loadClassForVdlName(String name) {
        String[] parts = name.split("/");
        for (int i = 0; i < parts.length - 1; i++) {
            List<String> subparts = Arrays.asList(parts[i].split("\\."));
            Collections.reverse(subparts);
            parts[i] = Joiner.on(".").join(subparts);
        }
        String className = Joiner.on(".").join(parts);
        try {
            // lookup and load class
            Class.forName(className);
            return true;
        } catch (ClassNotFoundException | NoClassDefFoundError e) {
            return false;
        }
    }

    private static synchronized VdlType synchronizedLookupOrBuildType(Type type) {
        if (typeCache.containsKey(type)) {
            return typeCache.get(type);
        }
        ReflectToVdlTypeBuilder builder = new ReflectToVdlTypeBuilder();
        PendingType pendingType = builder.lookupOrBuildPending(type);
        builder.buildAndCache();
        return pendingType.built();
    }

    /**
     * Builds VdlType from {@code java.lang.reflect.Type}. All results are cached in typeCahce.
     */
    private static final class ReflectToVdlTypeBuilder {
        private final Builder builder;
        private final Map<Type, PendingType> pendingTypes;

        public ReflectToVdlTypeBuilder() {
            builder = new Builder();
            pendingTypes = new HashMap<Type, PendingType>();
        }

        public void buildAndCache() {
            builder.build();
            for (Map.Entry<Type, PendingType> entry : pendingTypes.entrySet()) {
                Type reflectType = entry.getKey();
                VdlType vdlType = entry.getValue().built();
                typeCache.put(reflectType, vdlType);
                if (!Strings.isNullOrEmpty(vdlType.getName())) {
                    typeRegistry.put(vdlType, reflectType);
                }
            }
        }

        public PendingType lookupOrBuildPending(Type type) {
            PendingType vdlType = lookupType(type);
            if (vdlType != null) {
                return vdlType;
            }
            return buildPendingFromType(type);
        }

        private PendingType lookupType(Type type) {
            if (typeCache.containsKey(type)) {
                return builder.builtPendingFromType(typeCache.get(type));
            }
            if (pendingTypes.containsKey(type)) {
                return pendingTypes.get(type);
            }
            return null;
        }

        private PendingType buildPendingFromType(Type type) {
            Class<?> klass;
            Type[] elementTypes;
            if (type instanceof Class) {
                klass = (Class<?>) type;
                return buildPendingFromClass(klass);
            } else if (type instanceof ParameterizedType) {
                klass = (Class<?>) ((ParameterizedType) type).getRawType();
                elementTypes = ((ParameterizedType) type).getActualTypeArguments();
            } else if (type instanceof GenericArrayType) {
                klass = List.class;
                elementTypes = new Type[1];
                elementTypes[0] = (((GenericArrayType) type).getGenericComponentType());
            } else {
                throw new IllegalArgumentException("Unable to create VDL Type for type " + type);
            }

            PendingType pending;
            if (List.class.isAssignableFrom(klass)) {
                pending = builder.listOf(lookupOrBuildPending(elementTypes[0]));
            } else if (Set.class.isAssignableFrom(klass)) {
                pending = builder.setOf(lookupOrBuildPending(elementTypes[0]));
            } else if (Map.class.isAssignableFrom(klass)) {
                pending = builder.mapOf(lookupOrBuildPending(elementTypes[0]),
                        lookupOrBuildPending(elementTypes[1]));
            } else if (VdlOptional.class.isAssignableFrom(klass)) {
                pending = builder.optionalOf(lookupOrBuildPending(elementTypes[0]));
            } else {
                throw new IllegalArgumentException("Unable to create VDL Type for type " + type);
            }
            pendingTypes.put(type, pending);
            return pending;
        }


        private PendingType buildPendingFromClass(Class<?> klass) {
            PendingType pending;
            if (klass.isArray()) {
                pending = builder.listOf(lookupOrBuildPending(klass.getComponentType()));
                pendingTypes.put(klass, pending);
                return pending;
            }
            if (klass.isAssignableFrom(List.class)) {
                throw new IllegalArgumentException("Unable to create a VDL type from List.class." +
                        "  Consider creating a type using a TypeToken.");
            } else if (klass.isAssignableFrom(Set.class)) {
                throw new IllegalArgumentException("Unable to create a VDL type from Set.class." +
                        "  Consider creating a type using a TypeToken.");
            } else if (klass.isAssignableFrom(Map.class)) {
                throw new IllegalArgumentException("Unable to create a VDL type from Map.class." +
                        "  Consider creating a type using a TypeToken.");
            }
            pending = builder.newPending();
            pendingTypes.put(klass, pending);
            Class<?> superClass = klass.getSuperclass();
            if (superClass == VdlEnum.class) {
                populateEnum(pending, klass);
            } else if (superClass == AbstractVdlStruct.class) {
                if (klass == VdlStruct.class) {
                    throw new IllegalArgumentException("Unable to create VDL Type for " + klass);
                }
                populateStruct(pending, klass);
            } else if (superClass == VdlUnion.class) {
                populateUnion(pending, klass);
            } else if (superClass == VdlArray.class) {
                populateArray(pending, klass);
            } else if (superClass != null && superClass != Object.class) {
                pending.assignBase(lookupOrBuildPending(klass.getGenericSuperclass()));
            } else {
                // Attempt to decode as a struct.
                populateStruct(pending, klass);
            }
            GeneratedFromVdl annotation = klass.getAnnotation(GeneratedFromVdl.class);
            if (annotation != null) {
                pending.setName(annotation.name());
            } else if (klass.getCanonicalName() != null){
                pending.setName(klass.getCanonicalName());
            }
            return pending;
        }

        private void populateEnum(PendingType pending, Class<?> klass) {
            pending.setKind(Kind.ENUM);
            TreeMap<Integer, String> labels = new TreeMap<Integer, String>();
            for (Field field : klass.getDeclaredFields()) {
                GeneratedFromVdl annotation = field.getAnnotation(GeneratedFromVdl.class);
                if (annotation != null) {
                    labels.put(annotation.index(), annotation.name());
                }
            }
            for (Map.Entry<Integer, String> entry : labels.entrySet()) {
                pending.addLabel(entry.getValue());
            }
        }

        private void populateStruct(PendingType pending, Class<?> klass) {
            pending.setKind(Kind.STRUCT);
            TreeMap<Integer, PendingVdlField> fields = new TreeMap<Integer, PendingVdlField>();
            // See if the struct has any annotations.  If not, we assume user has provided
            // a raw class and we try to guess what the annotations would be.
            boolean hasFieldAnnotations = false;
            for (Field field : klass.getDeclaredFields()) {
                GeneratedFromVdl annotation = field.getAnnotation(GeneratedFromVdl.class);
                if (annotation != null) {
                    hasFieldAnnotations = true;
                    break;
                }
            }
            int fieldIndex = 0;
            for (Field field : klass.getDeclaredFields()) {
                if (Modifier.isStatic(field.getModifiers())) {  // skip static fields
                    continue;
                }
                if (Character.isUpperCase(field.getName().charAt(0))) {
                    throw new IllegalArgumentException("Java field names must be lower-cased");
                }
                GeneratedFromVdl annotation = field.getAnnotation(GeneratedFromVdl.class);
                if (annotation != null) {
                    fields.put(annotation.index(), new PendingVdlField(annotation.name(),
                            lookupOrBuildPending(field.getGenericType())));
                } else if (!hasFieldAnnotations) {
                    fields.put(++fieldIndex, new PendingVdlField(firstCharToUpper(field.getName()),
                            lookupOrBuildPending(field.getGenericType())));
                }
            }
            for (Map.Entry<Integer, PendingVdlField> entry : fields.entrySet()) {
                pending.addField(entry.getValue().name, entry.getValue().type);
            }
        }

        private void populateUnion(PendingType pending, Class<?> klass) {
            pending.setKind(Kind.UNION);
            TreeMap<Integer, PendingVdlField> fields = new TreeMap<Integer, PendingVdlField>();
            for (Class<?> unionClass : klass.getDeclaredClasses()) {
                GeneratedFromVdl annotation = unionClass.getAnnotation(GeneratedFromVdl.class);
                if (annotation == null) {
                    continue;
                }
                Type type;
                try {
                    type = unionClass.getDeclaredField("elem").getGenericType();
                } catch (Exception e) {
                    throw new IllegalArgumentException(
                            "Unable to create VDL Type for type " + klass, e);
                }
                String name = annotation.name().substring(annotation.name().lastIndexOf('$') + 1);
                fields.put(annotation.index(),
                        new PendingVdlField(name, lookupOrBuildPending(type)));
            }
            for (Map.Entry<Integer, PendingVdlField> entry : fields.entrySet()) {
                pending.addField(entry.getValue().name, entry.getValue().type);
            }
        }

        private void populateArray(PendingType pending, Class<?> klass) {
            pending.setKind(Kind.ARRAY);
            Type elementType = ((ParameterizedType) klass.getGenericSuperclass())
                    .getActualTypeArguments()[0];
            pending.setElem(lookupOrBuildPending(elementType));
            try {
                ArrayLength length = klass.getAnnotation(ArrayLength.class);
                pending.setLength(length.value());
            } catch (Exception e) {
                throw new IllegalArgumentException(
                        "Unable to create VDL Type for type " + klass, e);
            }
        }

        private static String firstCharToUpper(String str) {
            return Character.toUpperCase(str.charAt(0)) + str.substring(1);
        }

        private static final class PendingVdlField {
            final String name;
            final PendingType type;
            public PendingVdlField(String name, PendingType type) {
                this.name = name;
                this.type = type;
            }
        }
    }

    /**
     * A helper class used to create {@code Type} instances for VDL types.
     */
    private static class ParameterizedTypeImpl implements ParameterizedType {
        private final Type rawType;
        private final Type[] arguments;

        public ParameterizedTypeImpl(Type rawType, Type ... arguments) {
            this.rawType = rawType;
            this.arguments = arguments;
        }

        @Override
        public Type[] getActualTypeArguments() {
            return arguments;
        }

        @Override
        public Type getRawType() {
            return rawType;
        }

        @Override
        public Type getOwnerType() {
            return null;
        }
    }
}
