// 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.vom;

import io.v.v23.vdl.Kind;
import io.v.v23.vdl.Types;
import io.v.v23.vdl.VdlField;
import io.v.v23.vdl.VdlType;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * TypeCompatibility provides helpers to check compatibility of VDL types.
 */
public final class TypeCompatibility {
    /**
     * Returns true iff provided types are compatible.
     *
     * Compatibility is symmetric and transitive, except for the special Any type.
     * Here are the rules:
     *   o Any is compatible with all types.
     *   o Optional is ignored for all rules (e.g. ?int is treated as int).
     *   o Bool is only compatible with Bool.
     *   o TypeObject is only compatible with TypeObject.
     *   o Numbers are mutually compatible.
     *   o String, enum, []byte and [N]byte are mutually compatible.
     *   o Array and list are compatible if their elems are compatible.
     *   o Set, map and struct are compatible if all keys K* are compatible, and all fields F* are
     *     compatible:
     *     - map[string]F* is compatible with struct{_ F*; ...}
     *     - set[K*] is compatible with set[K*] and map[K*]bool
     *     - set[string] is compatible with struct{_ bool; ...}
     *     - Two struct types are compatible if all fields with the same name are
     *       compatible, and at least one field has the same name, or one of the
     *       types is an empty struct.
     *   o Two union types are compatible if all fields with the same name are
     *     compatible, and at least one field has the same name.
     */
    public static boolean compatible(VdlType a, VdlType b) {
        Map<VdlType, Set<VdlType>> seen = new HashMap<VdlType, Set<VdlType>>();
        return compatible(a, b, seen);
    }

    /**
     * Returns true iff provided types are compatible or a pair of types (a, b) was already visited.
     * It is OK to return true for visited type pairs as we need to find only one type compatibility
     * mismatch.
     *
     * @param seen the set of visited type pairs
     */
    private static boolean compatible(VdlType a, VdlType b, Map<VdlType, Set<VdlType>> seen) {
        // Remove optional wrapper.
        if (a.getKind() == Kind.OPTIONAL) {
            a = a.getElem();
        }
        if (b.getKind() == Kind.OPTIONAL) {
            b = b.getElem();
        }
        if (a == b) {
            return true;
        }
        // Look-up in seen.
        Set<VdlType> set = seen.get(a);
        if (set == null) {
            set = new HashSet<VdlType>();
            seen.put(a, set);
        }
        if (set.contains(b)) {
            return true;
        }
        set.add(b);
        // Handle Any.
        if (a.getKind() == Kind.ANY || b.getKind() == Kind.ANY) {
            return true;
        }
        // Handle simple scalar VDL types.
        if (isNumber(a)) {
            return isNumber(b);
        } else if (a.getKind() == Kind.BOOL) {
            return b.getKind() == Kind.BOOL;
        } else if (a.getKind() == Kind.TYPEOBJECT) {
            return b.getKind() == Kind.TYPEOBJECT;
        }
        // We must check if either a or b is []byte and handle it here first, to
        // ensure it doesn't fall through to the standard array/list handling.  This
        // ensures that []byte isn't compatible with []uint16 and other lists or
        // arrays of numbers.
        boolean aIsBytes = isStringEnumBytes(a), bIsBytes = isStringEnumBytes(b);
        if (aIsBytes|| bIsBytes) {
            return aIsBytes && bIsBytes;
        }
        // Handle composite VDL.
        switch (a.getKind()) {
            case ARRAY:
            case LIST:
                if (b.getKind() == Kind.ARRAY || b.getKind() == Kind.LIST) {
                    return compatible(a.getElem(), b.getElem(), seen);
                }
                return false;
            case MAP:
            case SET:
                switch (b.getKind()) {
                    case MAP:
                    case SET:
                        return mapsCompatible(a, b, seen);
                    case STRUCT:
                        return structAndMapCompatible(b, a, seen);
                    default:
                        return false;
                }
            case STRUCT:
                switch (b.getKind()) {
                    case MAP:
                    case SET:
                        return structAndMapCompatible(a, b, seen);
                    case STRUCT:
                        if (isEmptyStruct(a) || isEmptyStruct(b)) {
                            return true;
                        }
                        return fieldsCompatible(a, b, seen);
                    default:
                        return false;
                }
            case UNION:
                if (b.getKind() == Kind.UNION) {
                    return fieldsCompatible(a, b, seen);
                }
                return false;
            default:
                throw new IllegalArgumentException("Unsupported VDL type " + a);
        }
    }

    private static boolean isNumber(VdlType type) {
        switch (type.getKind()) {
            case BYTE:
            case COMPLEX128:
            case COMPLEX64:
            case FLOAT32:
            case FLOAT64:
            case INT16:
            case INT32:
            case INT64:
            case UINT16:
            case UINT32:
            case UINT64:
                return true;
            default:
                return false;
        }
    }

    private static boolean isStringEnumBytes(VdlType type) {
        return type.getKind() == Kind.STRING || type.getKind() == Kind.ENUM
                || BinaryUtil.isBytes(type);
    }

    private static boolean isEmptyStruct(VdlType type) {
        return type.getKind() == Kind.STRUCT && type.getFields().isEmpty();
    }

    private static boolean mapsCompatible(VdlType a, VdlType b, Map<VdlType, Set<VdlType>> seen) {
        if (!compatible(a.getKey(), b.getKey(), seen)) {
            return false;
        }
        VdlType aElem = a.getKind() == Kind.MAP ? a.getElem() : Types.BOOL;
        VdlType bElem = b.getKind() == Kind.MAP ? b.getElem() : Types.BOOL;
        return compatible(aElem, bElem, seen);
    }

    private static boolean structAndMapCompatible(VdlType struct, VdlType map,
            Map<VdlType, Set<VdlType>> seen) {
        if (isEmptyStruct(struct) || !compatible(Types.STRING, map.getKey(), seen)) {
            return false;
        }
        VdlType elem = map.getKind() == Kind.MAP ? map.getElem() : Types.BOOL;
        for (VdlField field : struct.getFields()) {
            if (!compatible(elem, field.getType(), seen)) {
                return false;
            }
        }
        return true;
    }

    private static boolean fieldsCompatible(VdlType a, VdlType b, Map<VdlType, Set<VdlType>> seen) {
        if (a.getFields().size() > b.getFields().size()) {
            return fieldsCompatible(b, a, seen);
        }
        Map<String, VdlType> aFields = new HashMap<String, VdlType>();
        for (VdlField field : a.getFields()) {
            aFields.put(field.getName(), field.getType());
        }
        boolean fieldMatched = false;
        for (VdlField field : b.getFields()) {
            VdlType type = aFields.get(field.getName());
            if (type != null) {
                if (!compatible(type, field.getType())) {
                    return false;
                }
                fieldMatched = true;
            }
        }
        return fieldMatched;
    }
}
