/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed 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 android.databinding.tool.store;

import android.databinding.tool.Context;
import android.databinding.tool.reflection.ModelAnalyzer;
import android.databinding.tool.reflection.ModelClass;
import android.databinding.tool.reflection.ModelMethod;
import android.databinding.tool.reflection.annotation.AnnotationTypeUtil;
import android.databinding.tool.util.GenerationalClassUtil;
import android.databinding.tool.util.L;
import android.databinding.tool.util.Preconditions;
import android.databinding.tool.util.StringUtils;

import com.android.annotations.NonNull;
import com.android.annotations.Nullable;

import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.stream.Collectors;

import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Types;

public class SetterStore {
    private static final int ASSIGNABLE_CONVERSION = 1;

    private final IntermediateV3 mStore;
    private final ModelAnalyzer mClassAnalyzer;
    private HashMap<String, List<String>> mInstanceAdapters;
    private final HashSet<String> mInverseEventAttributes = new HashSet<String>();

    private Comparator<MultiAttributeSetter> COMPARE_MULTI_ATTRIBUTE_SETTERS =
            new Comparator<MultiAttributeSetter>() {
                @Override
                public int compare(MultiAttributeSetter o1, MultiAttributeSetter o2) {
                    if (o1.attributes.length != o2.attributes.length) {
                        return o2.attributes.length - o1.attributes.length;
                    }
                    if (o1.mKey.attributeIndices.size() != o2.mKey.attributeIndices.size()) {
                        return o2.mKey.attributeIndices.size() - o1.mKey.attributeIndices.size();
                    }
                    ModelClass view1 = mClassAnalyzer.findClass(o1.mKey.viewType, null).erasure();
                    ModelClass view2 = mClassAnalyzer.findClass(o2.mKey.viewType, null).erasure();
                    if (!view1.equals(view2)) {
                        if (view1.isAssignableFrom(view2)) {
                            return 1;
                        } else {
                            return -1;
                        }
                    }
                    if (!o1.mKey.attributeIndices.keySet()
                            .equals(o2.mKey.attributeIndices.keySet())) {
                        // order by attribute name
                        Iterator<String> o1Keys = o1.mKey.attributeIndices.keySet().iterator();
                        Iterator<String> o2Keys = o2.mKey.attributeIndices.keySet().iterator();
                        while (o1Keys.hasNext() && o2Keys.hasNext()) {
                            String key1 = o1Keys.next();
                            String key2 = o2Keys.next();
                            int compare = key1.compareTo(key2);
                            if (compare != 0) {
                                return compare;
                            }
                        }
                        Preconditions.check(false,
                                "The sets don't match! That means the keys shouldn't match also");
                    }
                    // Same view type. Same attributes
                    for (String attribute : o1.mKey.attributeIndices.keySet()) {
                        final int index1 = o1.mKey.attributeIndices.get(attribute);
                        final int index2 = o2.mKey.attributeIndices.get(attribute);
                        ModelClass type1 = mClassAnalyzer
                                .findClass(o1.mKey.parameterTypes[index1], null);
                        ModelClass type2 = mClassAnalyzer
                                .findClass(o2.mKey.parameterTypes[index2], null);
                        if (type1.equals(type2)) {
                            continue;
                        }
                        if (o1.mCasts[index1] != null) {
                            if (o2.mCasts[index2] == null) {
                                return 1; // o2 is better
                            } else {
                                continue; // both are casts
                            }
                        } else if (o2.mCasts[index2] != null) {
                            return -1; // o1 is better
                        }
                        if (o1.mConverters[index1] != null) {
                            if (o2.mConverters[index2] == null) {
                                return 1; // o2 is better
                            } else {
                                continue; // both are conversions
                            }
                        } else if (o2.mConverters[index2] != null) {
                            return -1; // o1 is better
                        }

                        if (type1.isPrimitive()) {
                            if (type2.isPrimitive()) {
                                int type1ConversionLevel = ModelMethod
                                        .getImplicitConversionLevel(type1);
                                int type2ConversionLevel = ModelMethod
                                        .getImplicitConversionLevel(type2);
                                return type2ConversionLevel - type1ConversionLevel;
                            } else {
                                // type1 is primitive and has higher priority
                                return -1;
                            }
                        } else if (type2.isPrimitive()) {
                            return 1;
                        }
                        if (type1.isAssignableFrom(type2)) {
                            return 1;
                        } else if (type2.isAssignableFrom(type1)) {
                            return -1;
                        }
                    }
                    // hmmm... same view type, same attributes, same parameter types... ?
                    return 0;
                }
            };

    private SetterStore(ModelAnalyzer modelAnalyzer, IntermediateV3 store) {
        mClassAnalyzer = modelAnalyzer;
        mStore = store;
        for (HashMap<AccessorKey, InverseDescription> adapter : mStore.inverseAdapters.values()) {
            for (InverseDescription inverseDescription : adapter.values()) {
                mInverseEventAttributes.add(inverseDescription.event);
            }
        }
        for (HashMap<String, InverseDescription> method : mStore.inverseMethods.values()) {
            for (InverseDescription inverseDescription : method.values()) {
                mInverseEventAttributes.add(inverseDescription.event);
            }
        }
    }

    public static SetterStore get() {
        return Context.getSetterStore();
    }

    public static SetterStore create(ModelAnalyzer modelAnalyzer,
                                     GenerationalClassUtil generationalClassUtil) {
        return load(modelAnalyzer, generationalClassUtil);
    }

    private static SetterStore load(ModelAnalyzer modelAnalyzer,
                                    GenerationalClassUtil generationalClassUtil) {
        IntermediateV3 store = new IntermediateV3();
        List<Intermediate> previousStores = generationalClassUtil
                .loadObjects(GenerationalClassUtil.ExtensionFilter.SETTER_STORE);
        for (Intermediate intermediate : previousStores) {
            merge(store, intermediate);
        }
        return new SetterStore(modelAnalyzer, store);
    }

    public void addRenamedMethod(String attribute, String declaringClass, String method,
            TypeElement declaredOn) {
        attribute = stripNamespace(attribute);
        HashMap<String, MethodDescription> renamed = mStore.renamedMethods
                .computeIfAbsent(attribute, k -> new HashMap<>());
        MethodDescription methodDescription = new MethodDescription(
                declaredOn.getQualifiedName().toString(), method);
        L.d("STORE addmethod desc %s", methodDescription);
        renamed.put(declaringClass, methodDescription);
    }

    public void addInverseBindingMethod(String attribute, String event, String declaringClass,
            String method, TypeElement declaredOn) {
        attribute = stripNamespace(attribute);
        event = stripNamespace(event);
        HashMap<String, InverseDescription> inverseMethods = mStore.inverseMethods
                .computeIfAbsent(attribute, k -> new HashMap<>());
        InverseDescription methodDescription = new InverseDescription(
                declaredOn.getQualifiedName().toString(), method, event);
        L.d("STORE addInverseMethod desc %s", methodDescription);
        inverseMethods.put(declaringClass, methodDescription);
    }

    public void addInverseMethod(ProcessingEnvironment processingEnvironment,
            ExecutableElement method, ExecutableElement inverse) {
        InverseMethodDescription from = new InverseMethodDescription(processingEnvironment, method);
        InverseMethodDescription to = new InverseMethodDescription(processingEnvironment, inverse);

        String storedToName = mStore.twoWayMethods.get(from);
        if (storedToName != null && !to.method.equals(storedToName)) {
            throw new IllegalArgumentException(String.format(
                    "InverseMethod from %s to %s does not match expected method '%s'",
                    method, inverse, storedToName));
        }
        String storedFromName = mStore.twoWayMethods.get(to);
        if (storedFromName != null && !from.method.equals(storedFromName)) {
            throw new IllegalArgumentException(String.format(
                    "InverseMethod from %s to %s does not match expected method '%s'",
                    inverse, method, storedFromName));
        }
        mStore.twoWayMethods.put(from, to.method);
        mStore.twoWayMethods.put(to, from.method);
    }

    public void addBindingAdapter(ProcessingEnvironment processingEnv, String attribute,
            ExecutableElement bindingMethod, boolean takesComponent) {
        attribute = stripNamespace(attribute);
        L.d("STORE addBindingAdapter %s %s", attribute, bindingMethod);
        HashMap<AccessorKey, MethodDescription> adapters = mStore.adapterMethods
                .computeIfAbsent(attribute, k -> new HashMap<>());

        List<? extends VariableElement> parameters = bindingMethod.getParameters();
        final int viewIndex = takesComponent ? 1 : 0;
        TypeMirror viewType = eraseType(processingEnv, parameters.get(viewIndex).asType());
        String view = getQualifiedName(viewType);
        TypeMirror parameterType = eraseType(processingEnv, parameters.get(viewIndex + 1).asType());
        String value = getQualifiedName(parameterType);

        AccessorKey key = new AccessorKey(view, value);
        if (adapters.containsKey(key)) {
            throw new IllegalArgumentException("Already exists!");
        }

        adapters.put(key, new MethodDescription(bindingMethod, 1, takesComponent));
    }

    public void addInverseAdapter(ProcessingEnvironment processingEnv, String attribute,
            String event, ExecutableElement bindingMethod, boolean takesComponent) {
        attribute = stripNamespace(attribute);
        event = stripNamespace(event);
        L.d("STORE addInverseAdapter %s %s", attribute, bindingMethod);
        HashMap<AccessorKey, InverseDescription> adapters = mStore.inverseAdapters
                .computeIfAbsent(attribute, k -> new HashMap<>());

        List<? extends VariableElement> parameters = bindingMethod.getParameters();
        final int viewIndex = takesComponent ? 1 : 0;
        TypeMirror viewType = eraseType(processingEnv, parameters.get(viewIndex).asType());
        String view = getQualifiedName(viewType);
        TypeMirror returnType = eraseType(processingEnv, bindingMethod.getReturnType());
        String value = getQualifiedName(returnType);

        AccessorKey key = new AccessorKey(view, value);
        if (adapters.containsKey(key)) {
            throw new IllegalArgumentException("Already exists!");
        }

        adapters.put(key, new InverseDescription(bindingMethod, event, takesComponent));
    }

    private static TypeMirror eraseType(ProcessingEnvironment processingEnv,
            TypeMirror typeMirror) {
        if (hasTypeVar(typeMirror)) {
            return processingEnv.getTypeUtils().erasure(typeMirror);
        } else {
            return typeMirror;
        }
    }

    private static ModelClass eraseType(ModelClass modelClass) {
        if (hasTypeVar(modelClass)) {
            return modelClass.erasure();
        } else {
            return modelClass;
        }
    }

    private static boolean hasTypeVar(TypeMirror typeMirror) {
        TypeKind kind = typeMirror.getKind();
        if (kind == TypeKind.TYPEVAR) {
            return true;
        } else if (kind == TypeKind.ARRAY) {
            return hasTypeVar(((ArrayType) typeMirror).getComponentType());
        } else if (kind == TypeKind.DECLARED) {
            DeclaredType declaredType = (DeclaredType) typeMirror;
            List<? extends TypeMirror> typeArguments = declaredType.getTypeArguments();
            if (typeArguments == null || typeArguments.isEmpty()) {
                return false;
            }
            for (TypeMirror arg : typeArguments) {
                if (hasTypeVar(arg)) {
                    return true;
                }
            }
            return false;
        } else {
            return false;
        }
    }

    private static boolean hasTypeVar(ModelClass type) {
        if (type.isTypeVar()) {
            return true;
        } else if (type.isArray()) {
            return hasTypeVar(type.getComponentType());
        } else {
            List<ModelClass> typeArguments = type.getTypeArguments();
            if (typeArguments == null) {
                return false;
            }
            for (ModelClass arg : typeArguments) {
                if (hasTypeVar(arg)) {
                    return true;
                }
            }
            return false;
        }
    }

    public void addBindingAdapter(ProcessingEnvironment processingEnv, String[] attributes,
            ExecutableElement bindingMethod, boolean takesComponent, boolean requireAll) {
        L.d("STORE add multi-value BindingAdapter %d %s", attributes.length, bindingMethod);
        MultiValueAdapterKey key = new MultiValueAdapterKey(processingEnv, bindingMethod,
                attributes, takesComponent, requireAll);
        testRepeatedAttributes(key, bindingMethod);
        MethodDescription methodDescription = new MethodDescription(bindingMethod,
                attributes.length, takesComponent);
        mStore.multiValueAdapters.put(key, methodDescription);
    }

    private static void testRepeatedAttributes(MultiValueAdapterKey key, ExecutableElement method) {
        if (key.attributes.length != key.attributeIndices.size()) {
            HashSet<String> names = new HashSet<>();
            for (String attr : key.attributes) {
                if (names.contains(attr)) {
                    L.e(method, "Attribute \"" + attr + "\" is supplied multiple times in " +
                            "BindingAdapter " + method.toString());
                }
                names.add(attr);
            }
        }
    }

    private static String[] stripAttributes(String[] attributes) {
        String[] strippedAttributes = new String[attributes.length];
        for (int i = 0; i < attributes.length; i++) {
            if (attributes[i] != null) {
                strippedAttributes[i] = stripNamespace(attributes[i]);
            }
        }
        return strippedAttributes;
    }

    public void addUntaggableTypes(String[] typeNames, TypeElement declaredOn) {
        L.d("STORE addUntaggableTypes %s %s", Arrays.toString(typeNames), declaredOn);
        String declaredType = declaredOn.getQualifiedName().toString();
        for (String type : typeNames) {
            mStore.untaggableTypes.put(type, declaredType);
        }
    }

    private static String getQualifiedName(TypeMirror type) {
        final TypeKind kind = type.getKind();
        if (kind == TypeKind.ARRAY) {
            return getQualifiedName(((ArrayType) type).getComponentType()) + "[]";
        } else if (kind == TypeKind.DECLARED && isIncompleteType(type)) {
            DeclaredType declaredType = (DeclaredType) type;
            return declaredType.asElement().toString();
        } else {
            return ((AnnotationTypeUtil)AnnotationTypeUtil.getInstance()).toJava(type);
        }
    }

    private static boolean isIncompleteType(TypeMirror type) {
        final TypeKind kind = type.getKind();
        if (kind == TypeKind.TYPEVAR || kind == TypeKind.WILDCARD) {
            return true;
        } else if (kind == TypeKind.DECLARED) {
            DeclaredType declaredType = (DeclaredType) type;
            List<? extends TypeMirror> typeArgs = declaredType.getTypeArguments();
            if (typeArgs == null) {
                return false;
            }
            for (TypeMirror arg : typeArgs) {
                if (isIncompleteType(arg)) {
                    return true;
                }
            }
        }
        return false;
    }

    public void addConversionMethod(ExecutableElement conversionMethod) {
        L.d("STORE addConversionMethod %s", conversionMethod);
        List<? extends VariableElement> parameters = conversionMethod.getParameters();
        String fromType = getQualifiedName(parameters.get(0).asType());
        String toType = getQualifiedName(conversionMethod.getReturnType());
        MethodDescription methodDescription = new MethodDescription(conversionMethod, 1, false);
        HashMap<String, MethodDescription> convertTo = mStore.conversionMethods
                .computeIfAbsent(fromType, k -> new HashMap<>());
        convertTo.put(toType, methodDescription);
    }

    public void clear(Set<String> classes) {
        ArrayList<AccessorKey> removedAccessorKeys = new ArrayList<>();
        for (HashMap<AccessorKey, MethodDescription> adapters : mStore.adapterMethods.values()) {
            for (AccessorKey key : adapters.keySet()) {
                MethodDescription description = adapters.get(key);
                if (classes.contains(description.type)) {
                    removedAccessorKeys.add(key);
                }
            }
            removeFromMap(adapters, removedAccessorKeys);
        }

        ArrayList<String> removedRenamed = new ArrayList<>();
        for (HashMap<String, MethodDescription> renamed : mStore.renamedMethods.values()) {
            for (String key : renamed.keySet()) {
                if (classes.contains(renamed.get(key).type)) {
                    removedRenamed.add(key);
                }
            }
            removeFromMap(renamed, removedRenamed);
        }

        ArrayList<String> removedConversions = new ArrayList<>();
        for (HashMap<String, MethodDescription> convertTos : mStore.conversionMethods.values()) {
            for (String toType : convertTos.keySet()) {
                MethodDescription methodDescription = convertTos.get(toType);
                if (classes.contains(methodDescription.type)) {
                    removedConversions.add(toType);
                }
            }
            removeFromMap(convertTos, removedConversions);
        }

        ArrayList<String> removedUntaggable = new ArrayList<>();
        for (String typeName : mStore.untaggableTypes.keySet()) {
            if (classes.contains(mStore.untaggableTypes.get(typeName))) {
                removedUntaggable.add(typeName);
            }
        }
        removeFromMap(mStore.untaggableTypes, removedUntaggable);
    }

    private static <K, V> void removeFromMap(Map<K, V> map, List<K> keys) {
        for (K key : keys) {
            map.remove(key);
        }
        keys.clear();
    }

    public void write(String projectPackage, ProcessingEnvironment processingEnvironment)
            throws IOException {
        GenerationalClassUtil.get().writeIntermediateFile(projectPackage, projectPackage +
                        GenerationalClassUtil.ExtensionFilter.SETTER_STORE.getExtension(), mStore);
    }

    private static String stripNamespace(String attribute) {
        if (!attribute.startsWith("android:")) {
            int colon = attribute.indexOf(':');
            if (colon >= 0) {
                attribute = attribute.substring(colon + 1);
            }
        }
        return attribute;
    }

    public boolean isTwoWayEventAttribute(String attribute) {
        attribute = stripNamespace(attribute);
        return mInverseEventAttributes.contains(attribute);
    }
    public List<MultiAttributeSetter> getMultiAttributeSetterCalls(String[] attributes,
            ModelClass viewType, ModelClass[] valueType) {
        attributes = stripAttributes(attributes);
        final ArrayList<MultiAttributeSetter> calls = new ArrayList<MultiAttributeSetter>();
        if (viewType != null && viewType.isGeneric()) {
            List<ModelClass> viewGenerics = viewType.getTypeArguments();
            for (int i = 0; i < valueType.length; i++) {
                valueType[i] = eraseType(valueType[i], viewGenerics);
            }
            viewType = viewType.erasure();
        }
        ArrayList<MultiAttributeSetter> matching = getMatchingMultiAttributeSetters(attributes,
                viewType, valueType);
        Collections.sort(matching, COMPARE_MULTI_ATTRIBUTE_SETTERS);
        while (!matching.isEmpty()) {
            MultiAttributeSetter bestMatch = matching.get(0);
            calls.add(bestMatch);
            removeConsumedAttributes(matching, bestMatch.attributes);
        }
        return calls;
    }

    private static String simpleName(String className) {
        int dotIndex = className.lastIndexOf('.');
        if (dotIndex < 0) {
            return className;
        } else {
            return className.substring(dotIndex + 1);
        }
    }

    public Map<String, List<String>> getComponentBindingAdapters() {
        ensureInstanceAdapters();
        return mInstanceAdapters;
    }

    private String getBindingAdapterCall(String className) {
        ensureInstanceAdapters();
        final String simpleName = simpleName(className);
        List<String> adapters = mInstanceAdapters.get(simpleName);
        if (adapters.size() == 1) {
            return "get" + simpleName + "()";
        } else {
            int index = adapters.indexOf(className) + 1;
            return "get" + simpleName + index + "()";
        }
    }

    private void ensureInstanceAdapters() {
        if (mInstanceAdapters == null) {
            HashSet<String> adapters = new HashSet<String>();
            for (HashMap<AccessorKey, MethodDescription> methods : mStore.adapterMethods.values()) {
                for (MethodDescription method : methods.values()) {
                    if (!method.isStatic) {
                        adapters.add(method.type);
                    }
                }
            }
            for (MethodDescription method : mStore.multiValueAdapters.values()) {
                if (!method.isStatic) {
                    adapters.add(method.type);
                }
            }
            for (Map<AccessorKey, InverseDescription> methods : mStore.inverseAdapters.values()) {
                for (InverseDescription method : methods.values()) {
                    if (!method.isStatic) {
                        adapters.add(method.type);
                    }
                }
            }
            mInstanceAdapters = new HashMap<String, List<String>>();
            for (String adapter : adapters) {
                final String simpleName = simpleName(adapter);
                List<String> list = mInstanceAdapters.get(simpleName);
                if (list == null) {
                    list = new ArrayList<String>();
                    mInstanceAdapters.put(simpleName, list);
                }
                list.add(adapter);
            }
            for (List<String> list : mInstanceAdapters.values()) {
                if (list.size() > 1) {
                    Collections.sort(list);
                }
            }
        }
    }

    // Removes all MultiAttributeSetters that require any of the values in attributes
    private static void removeConsumedAttributes(ArrayList<MultiAttributeSetter> matching,
            String[] attributes) {
        for (int i = matching.size() - 1; i >= 0; i--) {
            final MultiAttributeSetter setter = matching.get(i);
            boolean found = false;
            for (String attribute : attributes) {
                if (isInArray(attribute, setter.attributes)) {
                    found = true;
                    break;
                }
            }
            if (found) {
                matching.remove(i);
            }
        }
    }

    // Linear search through the String array for a specific value.
    private static boolean isInArray(String str, String[] array) {
        for (String value : array) {
            if (value.equals(str)) {
                return true;
            }
        }
        return false;
    }

    private ArrayList<MultiAttributeSetter> getMatchingMultiAttributeSetters(String[] attributes,
            ModelClass viewType, ModelClass[] valueType) {
        final ArrayList<MultiAttributeSetter> setters = new ArrayList<MultiAttributeSetter>();
        for (MultiValueAdapterKey adapter : mStore.multiValueAdapters.keySet()) {
            if (adapter.requireAll && adapter.attributes.length > attributes.length) {
                continue;
            }
            ModelClass viewClass = mClassAnalyzer.findClass(adapter.viewType, null);
            if (viewClass.isGeneric()) {
                viewClass = viewClass.erasure();
            }
            if (!viewClass.isAssignableFrom(viewType)) {
                continue;
            }
            final MethodDescription method = mStore.multiValueAdapters.get(adapter);
            final MultiAttributeSetter setter = createMultiAttributeSetter(method, attributes,
                    valueType, adapter);
            if (setter != null) {
                setters.add(setter);
            }
        }
        return setters;
    }

    private MultiAttributeSetter createMultiAttributeSetter(MethodDescription method,
            String[] allAttributes, ModelClass[] attributeValues, MultiValueAdapterKey adapter) {
        int matchingAttributes = 0;
        String[] casts = new String[adapter.attributes.length];
        MethodDescription[] conversions = new MethodDescription[adapter.attributes.length];
        boolean[] supplied = new boolean[adapter.attributes.length];

        for (int i = 0; i < allAttributes.length; i++) {
            Integer index = adapter.attributeIndices.get(allAttributes[i]);
            if (index != null) {
                supplied[index] = true;
                matchingAttributes++;
                final String parameterTypeStr = adapter.parameterTypes[index];
                final ModelClass parameterType = eraseType(
                        mClassAnalyzer.findClass(parameterTypeStr, null));
                final ModelClass attributeType = attributeValues[i];
                if (!parameterType.isAssignableFrom(attributeType)) {
                    if (ModelMethod.isBoxingConversion(parameterType, attributeType)) {
                        // automatic boxing is ok
                        continue;
                    } else if (ModelMethod.isImplicitConversion(attributeType, parameterType)) {
                        // implicit conversion is ok
                        continue;
                    }
                    // Look for a converter
                    conversions[index] = getConversionMethod(attributeType, parameterType, null);
                    if (conversions[index] == null) {
                        if (attributeType.isObject()) {
                            // Cast is allowed also
                            casts[index] = parameterTypeStr;
                        } else {
                            // Parameter type mismatch
                            return null;
                        }
                    }
                }
            }
        }

        if ((adapter.requireAll && matchingAttributes != adapter.attributes.length) ||
                matchingAttributes == 0) {
            return null;
        } else {
            return new MultiAttributeSetter(adapter, supplied, method, conversions, casts);
        }
    }

    public SetterCall getSetterCall(String attribute, ModelClass viewType,
            ModelClass valueType, Map<String, String> imports) {
        if (viewType == null) {
            return null;
        }

        viewType = viewType.erasure();
        attribute = stripNamespace(attribute);
        ModelClass bestViewType = null;
        ModelClass bestValueType = null;
        SetterCall setterCall = null;
        ModelMethod bestSetterMethod = getBestSetter(viewType, valueType, attribute, imports);
        if (bestSetterMethod != null) {
            bestViewType = bestSetterMethod.getReceiverType();
            bestValueType = bestSetterMethod.getParameterTypes()[0];
            setterCall = new ModelMethodSetter(bestSetterMethod);
        }

        HashMap<AccessorKey, MethodDescription> adapters = mStore.adapterMethods.get(attribute);
        if (adapters != null) {
            for (AccessorKey key : adapters.keySet()) {
                try {
                    ModelClass adapterViewType =
                            mClassAnalyzer.findClass(key.viewType, imports).erasure();
                    if (adapterViewType != null && adapterViewType.isAssignableFrom(viewType)) {
                        try {
                            L.d("setter parameter type is %s", key.valueType);
                            final ModelClass adapterValueType = eraseType(mClassAnalyzer
                                    .findClass(key.valueType, imports));
                            MethodDescription adapter = adapters.get(key);
                            L.d("setter %s takes type %s, compared to %s",
                                    adapter.method, adapterValueType.toJavaCode(),
                                    valueType.toJavaCode());
                            if (isBetterParameter(valueType, adapterViewType, adapterValueType,
                                    bestViewType, bestValueType, imports)) {
                                final ModelClass adapterClass = mClassAnalyzer
                                        .findClass(adapter.type, imports);
                                if (adapterClass == null) {
                                    // adapter is not in compile classpath, probably in runtime
                                    // classpath hence we should ignore it.
                                    L.d("ignoring adapter %s because it is not in the" +
                                            " compile classpath.", adapter.type);
                                    continue;
                                }
                                bestViewType = adapterViewType;
                                bestValueType = adapterValueType;
                                setterCall = new AdapterSetter(adapter, adapterValueType);
                            }
                        } catch (Exception e) {
                            L.e(e, "Unknown class: %s", key.valueType);
                        }
                    }
                } catch (Exception e) {
                    L.e(e, "Unknown class: %s", key.viewType);
                }
            }
        }

        if (setterCall != null) {
            if (valueType.isObject() && bestValueType.isNullable()) {
                setterCall.setCast(bestValueType);
            }
            MethodDescription conversionMethod = getConversionMethod(valueType, bestValueType, imports);
            setterCall.setConverter(conversionMethod);
        }

        return setterCall;
    }

    public BindingGetterCall getGetterCall(String attribute, ModelClass viewType,
            ModelClass valueType, Map<String, String> imports) {
        if (viewType == null) {
            return null;
        } else if (viewType.isViewDataBinding()) {
            return new ViewDataBindingGetterCall(viewType, attribute);
        }

        attribute = stripNamespace(attribute);
        viewType = viewType.erasure();

        InverseMethod bestMethod = getBestGetter(viewType, valueType, attribute, imports);
        HashMap<AccessorKey, InverseDescription> adapters = mStore.inverseAdapters.get(attribute);
        if (adapters != null) {
            for (AccessorKey key : adapters.keySet()) {
                try {
                    ModelClass adapterViewType = mClassAnalyzer
                            .findClass(key.viewType, imports).erasure();
                    if (adapterViewType != null && adapterViewType.isAssignableFrom(viewType)) {
                        try {
                            L.d("getter return type is %s", key.valueType);
                            final ModelClass adapterValueType = eraseType(mClassAnalyzer
                                    .findClass(key.valueType, imports));
                            L.d("getter %s returns type %s, compared to %s",
                                    adapters.get(key).method, adapterValueType.toJavaCode(),
                                    valueType);
                            if (valueType == null ||
                                    isBetterReturn(valueType, adapterViewType, adapterValueType,
                                            bestMethod.viewType, bestMethod.returnType, imports)) {
                                bestMethod.viewType = adapterViewType;
                                bestMethod.returnType = adapterValueType;
                                InverseDescription inverseDescription = adapters.get(key);
                                ModelAnalyzer modelAnalyzer = ModelAnalyzer.getInstance();
                                ModelClass listenerType = modelAnalyzer.findClass(
                                        modelAnalyzer.libTypes.getInverseBindingListener(),
                                        Collections.emptyMap());
                                BindingSetterCall eventCall = getSetterCall(
                                        inverseDescription.event, viewType, listenerType, imports);
                                if (eventCall == null) {
                                    List<MultiAttributeSetter> setters =
                                            getMultiAttributeSetterCalls(
                                                    new String[]{inverseDescription.event},
                                                    viewType, new ModelClass[] {listenerType});
                                    if (setters.size() != 1) {
                                        L.e("Could not find event '%s' on View type '%s'",
                                                inverseDescription.event,
                                                viewType.getCanonicalName());
                                    } else {
                                        bestMethod.call = new AdapterGetter(inverseDescription,
                                                setters.get(0), key.valueType);
                                    }
                                } else {
                                    bestMethod.call = new AdapterGetter(inverseDescription,
                                            eventCall, key.valueType);
                                }
                            }

                        } catch (Exception e) {
                            L.e(e, "Unknown class: %s", key.valueType);
                        }
                    }
                } catch (Exception e) {
                    L.e(e, "Unknown class: %s", key.viewType);
                }
            }
        }

        return bestMethod.call;
    }

    public String getInverseMethod(ModelMethod method) {
        InverseMethodDescription description = new InverseMethodDescription(method);
        return mStore.twoWayMethods.get(description);
    }

    public boolean isUntaggable(String viewType) {
        return mStore.untaggableTypes.containsKey(viewType);
    }

    private ModelMethod getBestSetter(ModelClass viewType, ModelClass argumentType,
            String attribute, Map<String, String> imports) {
        if (viewType.isGeneric()) {
            argumentType = eraseType(argumentType, viewType.getTypeArguments());
            viewType = viewType.erasure();
        }
        List<String> setterCandidates = new ArrayList<>();
        HashMap<String, MethodDescription> renamed = mStore.renamedMethods.get(attribute);
        if (renamed != null) {
            for (String className : renamed.keySet()) {
                try {
                    ModelClass renamedViewType = mClassAnalyzer.findClass(className, imports);
                    if (renamedViewType.erasure().isAssignableFrom(viewType)) {
                        setterCandidates.add(renamed.get(className).method);
                        break;
                    }
                } catch (Exception e) {
                    //printMessage(Diagnostic.Kind.NOTE, "Unknown class: " + className);
                }
            }
        }
        setterCandidates.add(getSetterName(attribute));
        setterCandidates.add(trimAttributeNamespace(attribute));

        ModelMethod bestMethod = null;
        ModelClass bestParameterType = null;
        List<ModelClass> args = new ArrayList<ModelClass>();
        args.add(argumentType);
        for (String name : setterCandidates) {
            ModelMethod[] methods = viewType.getMethods(name, 1);

            for (ModelMethod method : methods) {
                ModelClass[] parameterTypes = method.getParameterTypes();
                ModelClass param = parameterTypes[0];
                ModelClass previousViewType = bestParameterType == null ? null : viewType;
                if (method.isVoid() && isBetterParameter(argumentType, viewType, param,
                        previousViewType, bestParameterType, imports)) {
                    bestParameterType = param;
                    bestMethod = method;
                }
            }
        }
        return bestMethod;
    }

    private InverseMethod getBestGetter(ModelClass viewType, ModelClass valueType,
            String attribute, Map<String, String> imports) {
        if (viewType.isGeneric()) {
            if (valueType != null) {
                valueType = eraseType(valueType, viewType.getTypeArguments());
            }
            viewType = viewType.erasure();
        }
        ModelClass bestReturnType = null;
        InverseDescription bestDescription = null;
        ModelClass bestViewType = null;
        ModelMethod bestMethod = null;

        HashMap<String, InverseDescription> inverseMethods = mStore.inverseMethods.get(attribute);
        if (inverseMethods != null) {
            for (String className : inverseMethods.keySet()) {
                try {
                    ModelClass methodViewType = mClassAnalyzer.findClass(className, imports);
                    if (methodViewType.erasure().isAssignableFrom(viewType)) {
                        final InverseDescription inverseDescription = inverseMethods.get(className);
                        final String name = inverseDescription.method.isEmpty() ?
                                trimAttributeNamespace(attribute) : inverseDescription.method;
                        ModelMethod method = methodViewType.findInstanceGetter(name);
                        ModelClass returnType = method.getReturnType(null); // no parameters
                        if (valueType == null || bestReturnType == null ||
                                isBetterReturn(valueType, methodViewType, returnType,
                                        bestViewType, bestReturnType, imports)) {
                            bestDescription = inverseDescription;
                            bestReturnType = returnType;
                            bestViewType = methodViewType;
                            bestMethod = method;
                        }
                    }
                } catch (Exception e) {
                    L.d(e, "Unknown class: " + className);
                }
            }
        }

        BindingGetterCall call = null;
        if (bestDescription != null) {
            ModelAnalyzer modelAnalyzer = ModelAnalyzer.getInstance();
            final ModelClass listenerType = modelAnalyzer.findClass(
                    modelAnalyzer.libTypes.getInverseBindingListener(), Collections.emptyMap());
            SetterCall eventSetter = getSetterCall(bestDescription.event, viewType,
                    listenerType, imports);
            if (eventSetter == null) {
                List<MultiAttributeSetter> setters = getMultiAttributeSetterCalls(
                        new String[] {bestDescription.event}, viewType,
                        new ModelClass[] {listenerType});
                if (setters.size() != 1) {
                    L.e("Could not find event '%s' on View type '%s'", bestDescription.event,
                            viewType.getCanonicalName());
                    bestViewType = null;
                    bestReturnType = null;
                } else {
                    call = new ViewGetterCall(bestDescription, bestMethod, setters.get(0));
                }
            } else {
                call = new ViewGetterCall(bestDescription, bestMethod, eventSetter);
            }
        }
        return new InverseMethod(call, bestReturnType, bestViewType);
    }

    private static ModelClass eraseType(ModelClass type, List<ModelClass> typeParameters) {
        List<ModelClass> typeArguments = type.getTypeArguments();
        if (typeArguments == null || typeParameters == null) {
            return type;
        }
        for (ModelClass arg : typeArguments) {
            if (typeParameters.contains(arg)) {
                return type.erasure();
            }
        }
        return type;
    }

    private static String trimAttributeNamespace(String attribute) {
        final int colonIndex = attribute.indexOf(':');
        return colonIndex == -1 ? attribute : attribute.substring(colonIndex + 1);
    }

    private static String getSetterName(String attribute) {
        return "set" + StringUtils.capitalize(trimAttributeNamespace(attribute));
    }

    /**
     * Checks to see if one parameter is a better fit for a setter (e.g. BindingAdapter) than
     * another for an argument. It is assumed that both view types match the targeted view.
     * <p>
     * Note that this has different priorities than
     * {@link #isBetterReturn(ModelClass, ModelClass, ModelClass, ModelClass, ModelClass, Map)}
     *
     * @param argument The argument type being passed to the setter.
     * @param newViewType The type of the view in the BindingAdapter or setter method.
     * @param newParameter The parameter type of the value in the BindingAdapter or setter method.
     * @param oldViewType The type of the view in the previous matching BindingAdapter or setter
     *                   method.
     * @param oldParameter The parameter type of the value in the previous matching BindingAdapter
     *                    or setter method.
     * @param imports Import in the binding layout file.
     * @return {@code true} when the new BindingAdapter or setter method is a better fit than the
     * previous one or {@code false} if {@code argument} and {@code newParameter} aren't a match
     * or are a worse match.
     */
    private boolean isBetterParameter(@NonNull ModelClass argument,
            @NonNull ModelClass newViewType, @NonNull ModelClass newParameter,
            @Nullable ModelClass oldViewType, @Nullable ModelClass oldParameter,
            @Nullable Map<String, String> imports) {
        if (oldParameter == null) {
            // just validate that it can be converted
            return calculateConversionPriority(argument, newParameter, imports) >= 0;
        }

        int newConversion = calculateConversionPriority(argument, newParameter, imports);
        if (newConversion < 0) {
            return false; // Doesn't convert
        }

        boolean isSameViewType = oldViewType.equals(newViewType);
        boolean isBetterViewType = oldViewType.isAssignableFrom(newViewType);

        int oldConversion = calculateConversionPriority(argument, oldParameter, imports);
        if (oldConversion == ASSIGNABLE_CONVERSION && newConversion == ASSIGNABLE_CONVERSION) {
            if (isSameViewType) {
                // more specific getter is better
                return oldParameter.isAssignableFrom(newParameter);
            } else {
                return isBetterViewType;
            }
        }

        if (isSameViewType) {
            return newConversion <= oldConversion;
        }

        if (newConversion == oldConversion) {
            return isBetterViewType;
        }

        return newConversion <= oldConversion;
    }

    /**
     * Checks to see if one return type is a better fit for a getter (e.g. InverseBindingAdapter)
     * than another for a method call. It is assumed that both view types match the targeted view.
     * <p>
     * Note that this has different priorities than
     * {@link #isBetterParameter(ModelClass, ModelClass, ModelClass, ModelClass, ModelClass, Map)}
     *
     * @param expected The type that is expected from the getter.
     * @param newViewType The type of the view in the InverseBindingAdapter or getter method.
     * @param newReturnType The return type of the value in the InverseBindingAdapter or getter
     *                      method.
     * @param oldViewType The type of the view in the previous matching InverseBindingAdapter or
     *                    getter method.
     * @param oldReturnType The return type of the value in the previous matching
     *                     InverseBindingAdapter or getter method.
     * @param imports Import in the binding layout file.
     * @return {@code true} when the new InverseBindingAdapter or getter method is a better fit
     * than the previous one or {@code false} if {@code expected} and {@code newReturnType} aren't
     * a match or are a worse match.
     */
    private boolean isBetterReturn(@NonNull ModelClass expected,
            @NonNull ModelClass newViewType, @NonNull ModelClass newReturnType,
            @Nullable ModelClass oldViewType, @Nullable ModelClass oldReturnType,
            @Nullable Map<String, String> imports) {
        if (oldReturnType == null) {
            // just validate that it can be converted
            return calculateConversionPriority(newReturnType, expected, imports) >= 0;
        }

        int newConversion = calculateConversionPriority(newReturnType, expected, imports);
        if (newConversion < 0) {
            return false; // Doesn't convert
        }

        boolean isSameViewType = oldViewType.equals(newViewType);
        boolean isBetterViewType = oldViewType.isAssignableFrom(newViewType);

        int oldConversion = calculateConversionPriority(oldReturnType, expected, imports);
        if (oldConversion == ASSIGNABLE_CONVERSION && newConversion == ASSIGNABLE_CONVERSION) {
            if (isSameViewType) {
                // more generic getter is better (fairly arbitrary, but consistent)
                return newReturnType.isAssignableFrom(oldReturnType);
            } else {
                return isBetterViewType;
            }
        }

        if (isSameViewType) {
            return newConversion <= oldConversion;
        }

        if (newConversion == oldConversion) {
            return isBetterViewType;
        }

        return newConversion <= oldConversion;
    }

    /**
     * When calling a method, the closer an argument is to the declared parameter, the
     * more likely it is to be matched. This method returns -1 when a {@code from} does not
     * match {@code to}, 0 for an exact match, ASSIGNABLE_CONVERSION when {@code from} is a
     * superclass or interface of {@code to}, and higher values for progressively more inexact
     * matches.
     *
     * @param from The class or interface to attempt to convert from
     * @param to The class or interface to attempt to convert to
     * @param imports The imports used in this binding file
     * @return {@code -1} for no match or greater than or equal to {@code 0} for a possible match,
     * where {@code 0} is an exact match and greater numbers are progressively worse matches.
     */
    private int calculateConversionPriority(@NonNull ModelClass from, @NonNull ModelClass to,
            @Nullable Map<String, String> imports) {
        if (to.equals(from)) {
            return 0; // exact match
        }
        if (to.isAssignableFrom(from)) {
            return ASSIGNABLE_CONVERSION;
        }
        if (ModelMethod.isBoxingConversion(from, to)) {
            return 2;
        }
        if (ModelMethod.isImplicitConversion(from, to)) {
            // this should be 3 - 9
            return 3 + ModelMethod.getImplicitConversionLevel(to);
        }
        if (getConversionMethod(from, to, imports) != null) {
            return 10;
        }
        if (from.isObject() && !to.isPrimitive()) {
            return 11;
        }
        return -1;
    }

    private MethodDescription getConversionMethod(ModelClass from, ModelClass to,
            Map<String, String> imports) {
        if (from != null && to != null) {
            if (to.isObject()) {
                return null;
            }
            for (String fromClassName : mStore.conversionMethods.keySet()) {
                try {
                    ModelClass convertFrom = mClassAnalyzer.findClass(fromClassName, imports);
                    if (canUseForConversion(from, convertFrom)) {
                        HashMap<String, MethodDescription> conversion =
                                mStore.conversionMethods.get(fromClassName);
                        for (String toClassName : conversion.keySet()) {
                            try {
                                ModelClass convertTo = mClassAnalyzer.findClass(toClassName,
                                        imports);
                                if (canUseForConversion(convertTo, to)) {
                                    return conversion.get(toClassName);
                                }
                            } catch (Exception e) {
                                L.d(e, "Unknown class: %s", toClassName);
                            }
                        }
                    }
                } catch (Exception e) {
                    L.d(e, "Unknown class: %s", fromClassName);
                }
            }
        }
        return null;
    }

    private boolean canUseForConversion(ModelClass from, ModelClass to) {
        if (from.isIncomplete() || to.isIncomplete()) {
            from = from.erasure();
            to = to.erasure();
        }
        return from.equals(to) || ModelMethod.isBoxingConversion(from, to) ||
                to.isAssignableFrom(from);
    }

    private static void merge(IntermediateV3 store, Intermediate dumpStore) {
        IntermediateV3 intermediateV3 = (IntermediateV3) dumpStore.upgrade();
        merge(store.adapterMethods, intermediateV3.adapterMethods);
        merge(store.renamedMethods, intermediateV3.renamedMethods);
        merge(store.conversionMethods, intermediateV3.conversionMethods);
        store.multiValueAdapters.putAll(intermediateV3.multiValueAdapters);
        store.untaggableTypes.putAll(intermediateV3.untaggableTypes);
        merge(store.inverseAdapters, intermediateV3.inverseAdapters);
        merge(store.inverseMethods, intermediateV3.inverseMethods);
        store.twoWayMethods.putAll(intermediateV3.twoWayMethods);
    }

    private static <K, V, D> void merge(HashMap<K, HashMap<V, D>> first,
            HashMap<K, HashMap<V, D>> second) {
        for (K key : second.keySet()) {
            HashMap<V, D> firstVals = first.get(key);
            HashMap<V, D> secondVals = second.get(key);
            if (firstVals == null) {
                first.put(key, secondVals);
            } else {
                for (V key2 : secondVals.keySet()) {
                    if (!firstVals.containsKey(key2)) {
                        firstVals.put(key2, secondVals.get(key2));
                    }
                }
            }
        }
    }

    private static String createAdapterCall(MethodDescription adapter,
            String componentExpression, String viewExpression, String... args) {
        StringBuilder sb = new StringBuilder();

        if (adapter.isStatic) {
            sb.append(adapter.type);
        } else {
            final SetterStore setterStore = SetterStore.get();
            final String binderCall =  setterStore.getBindingAdapterCall(adapter.type);
            sb.append(componentExpression).append('.').append(binderCall);
        }
        sb.append('.').append(adapter.method).append('(');
        if (adapter.componentClass != null) {
            if (!"DataBindingComponent".equals(adapter.componentClass)) {
                sb.append('(').append(adapter.componentClass).append(") ");
            }
            sb.append(componentExpression).append(", ");
        }
        sb.append(viewExpression);
        for (String arg: args) {
            sb.append(", ").append(arg);
        }
        sb.append(')');
        return sb.toString();
    }

    private static class MultiValueAdapterKey implements Serializable {
        private static final long serialVersionUID = 1;

        public final String viewType;

        public final String[] attributes;

        public final String[] parameterTypes;

        public final boolean requireAll;

        public final TreeMap<String, Integer> attributeIndices = new TreeMap<String, Integer>();

        public MultiValueAdapterKey(ProcessingEnvironment processingEnv,
                ExecutableElement method, String[] attributes, boolean takesComponent,
                boolean requireAll) {
            this.attributes = stripAttributes(attributes);
            this.requireAll = requireAll;
            List<? extends VariableElement> parameters = method.getParameters();
            final int argStart = 1 + (takesComponent ? 1 : 0);
            this.viewType = getQualifiedName(eraseType(processingEnv,
                    parameters.get(argStart - 1).asType()));
            this.parameterTypes = new String[attributes.length];
            for (int i = 0; i < attributes.length; i++) {
                TypeMirror typeMirror = eraseType(processingEnv,
                        parameters.get(i + argStart).asType());
                this.parameterTypes[i] = getQualifiedName(typeMirror);
                attributeIndices.put(this.attributes[i], i);
            }
        }

        @Override
        public boolean equals(Object obj) {
            if (!(obj instanceof MultiValueAdapterKey)) {
                return false;
            }
            final MultiValueAdapterKey that = (MultiValueAdapterKey) obj;
            if (!this.viewType.equals(that.viewType) ||
                    this.attributes.length != that.attributes.length ||
                    !this.attributeIndices.keySet().equals(that.attributeIndices.keySet())) {
                return false;
            }

            for (int i = 0; i < this.attributes.length; i++) {
                final int thatIndex = that.attributeIndices.get(this.attributes[i]);
                final String thisParameter = parameterTypes[i];
                final String thatParameter = that.parameterTypes[thatIndex];
                if (!thisParameter.equals(thatParameter)) {
                    return false;
                }
            }
            return true;
        }

        @Override
        public int hashCode() {
            return mergedHashCode(viewType, attributeIndices.keySet());
        }
    }

    private static int mergedHashCode(Object... objects) {
        return Arrays.hashCode(objects);
    }

    private static class MethodDescription implements Serializable {

        private static final long serialVersionUID = 1;

        public final String type;

        public final String method;

        public final boolean requiresOldValue;

        public final boolean isStatic;

        public final String componentClass;

        public MethodDescription(String type, String method) {
            this.type = type;
            this.method = method;
            this.requiresOldValue = false;
            this.isStatic = true;
            this.componentClass = null;
            L.d("BINARY created method desc 1 %s %s", type, method );
        }

        public MethodDescription(ExecutableElement method, int numAttributes,
                boolean takesComponent) {
            TypeElement enclosingClass = (TypeElement) method.getEnclosingElement();
            this.type = enclosingClass.getQualifiedName().toString();
            this.method = method.getSimpleName().toString();
            final int argStart = 1 + (takesComponent ? 1 : 0);
            this.requiresOldValue = method.getParameters().size() - argStart == numAttributes * 2;
            this.isStatic = method.getModifiers().contains(Modifier.STATIC);
            this.componentClass = takesComponent
                    ? getQualifiedName(method.getParameters().get(0).asType())
                    : null;

            L.d("BINARY created method desc 2 %s %s, %s", type, this.method, method);
        }

        @Override
        public boolean equals(Object obj) {
            if (obj instanceof MethodDescription) {
                MethodDescription that = (MethodDescription) obj;
                return that.type.equals(this.type) && that.method.equals(this.method);
            } else {
                return false;
            }
        }

        @Override
        public int hashCode() {
            return mergedHashCode(type, method);
        }

        @Override
        public String toString() {
            return type + "." + method + "()";
        }
    }

    private static class InverseDescription extends MethodDescription {
        private static final long serialVersionUID = 1;

        public final String event;

        public InverseDescription(String type, String method, String event) {
            super(type, method);
            this.event = event;
        }

        public InverseDescription(ExecutableElement method, String event, boolean takesComponent) {
            super(method, 1, takesComponent);
            this.event = event;
        }

        @Override
        public boolean equals(Object obj) {
            if (!super.equals(obj) || !(obj instanceof InverseDescription)) {
                return false;
            }
            return event.equals(((InverseDescription) obj).event);
        }

        @Override
        public int hashCode() {
            return mergedHashCode(type, method, event);
        }
    }

    private static class AccessorKey implements Serializable {

        private static final long serialVersionUID = 1;

        public final String viewType;

        public final String valueType;

        public AccessorKey(String viewType, String valueType) {
            this.viewType = viewType;
            this.valueType = valueType;
        }

        @Override
        public int hashCode() {
            return mergedHashCode(viewType, valueType);
        }

        @Override
        public boolean equals(Object obj) {
            if (obj instanceof AccessorKey) {
                AccessorKey that = (AccessorKey) obj;
                return viewType.equals(that.valueType) && valueType.equals(that.valueType);
            } else {
                return false;
            }
        }

        @Override
        public String toString() {
            return "AK(" + viewType + ", " + valueType + ")";
        }
    }

    private static class InverseMethodDescription implements Serializable {
        private static final long serialVersionUID = 0xC00L;

        public final boolean isStatic;
        public final String returnType;
        public final String method;
        public final String[] parameterTypes;
        public final String type;

        public InverseMethodDescription(ProcessingEnvironment env, ExecutableElement method) {
            this.isStatic = method.getModifiers().contains(Modifier.STATIC);
            Types typeUtils = env.getTypeUtils();
            this.returnType = getQualifiedName(typeUtils.erasure(method.getReturnType()));
            this.method = method.getSimpleName().toString();
            TypeElement enclosingClass = (TypeElement) method.getEnclosingElement();
            this.type = enclosingClass.getQualifiedName().toString();

            List<? extends VariableElement> parameters = method.getParameters();
            this.parameterTypes = new String[parameters.size()];

            for (int i = 0; i < parameters.size(); i++) {
                VariableElement param  = parameters.get(i);
                TypeMirror type = typeUtils.erasure(param.asType());
                this.parameterTypes[i] = getQualifiedName(type);
            }
        }

        public InverseMethodDescription(ModelMethod method) {
            this.isStatic = method.isStatic();
            this.returnType = method.getReturnType().erasure().getCanonicalName();
            this.method = method.getName();
            this.type = method.getReceiverType().getCanonicalName();

            ModelClass[] parameters = method.getParameterTypes();
            this.parameterTypes = new String[parameters.length];

            for (int i = 0; i < parameters.length; i++) {
                this.parameterTypes[i] = parameters[i].erasure().getCanonicalName();
            }
        }

        @Override
        public int hashCode() {
            return mergedHashCode(type, isStatic, returnType, method,
                    Arrays.hashCode(parameterTypes));
        }

        @Override
        public boolean equals(Object obj) {
            if (obj instanceof InverseMethodDescription) {
                InverseMethodDescription that = (InverseMethodDescription) obj;
                return this.isStatic == that.isStatic &&
                        this.type.equals(that.type) &&
                        this.returnType.equals(that.returnType) &&
                        this.method.equals(that.method) &&
                        Arrays.equals(this.parameterTypes, that.parameterTypes);
            } else {
                return false;
            }
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            if (isStatic) {
                sb.append("static ");
            }
            sb.append(returnType)
                    .append(' ')
                    .append(type)
                    .append('.')
                    .append(method)
                    .append('(');
            for (int i = 0; i < parameterTypes.length; i++) {
                if (i != 0) {
                    sb.append(", ");
                }
                sb.append(parameterTypes[i]);
            }
            sb.append(')');
            return sb.toString();
        }
    }

    private interface Intermediate extends Serializable {
        Intermediate upgrade();
    }

    private static class IntermediateV1 implements Serializable, Intermediate {
        private static final long serialVersionUID = 1;
        public final HashMap<String, HashMap<AccessorKey, MethodDescription>> adapterMethods =
                new HashMap<String, HashMap<AccessorKey, MethodDescription>>();
        public final HashMap<String, HashMap<String, MethodDescription>> renamedMethods =
                new HashMap<String, HashMap<String, MethodDescription>>();
        public final HashMap<String, HashMap<String, MethodDescription>> conversionMethods =
                new HashMap<String, HashMap<String, MethodDescription>>();
        public final HashMap<String, String> untaggableTypes = new HashMap<String, String>();
        public final HashMap<MultiValueAdapterKey, MethodDescription> multiValueAdapters =
                new HashMap<MultiValueAdapterKey, MethodDescription>();

        public IntermediateV1() {
        }

        @Override
        public Intermediate upgrade() {
            IntermediateV2 v2 = new IntermediateV2();
            v2.adapterMethods.putAll(adapterMethods);
            v2.renamedMethods.putAll(renamedMethods);
            v2.conversionMethods.putAll(conversionMethods);
            v2.untaggableTypes.putAll(untaggableTypes);
            v2.multiValueAdapters.putAll(multiValueAdapters);
            return v2.upgrade();
        }
    }

    private static class IntermediateV2 extends IntermediateV1 {
        private static final long serialVersionUID = 0xA45C2EB637E35C07L;
        public final HashMap<String, HashMap<AccessorKey, InverseDescription>> inverseAdapters =
                new HashMap<String, HashMap<AccessorKey, InverseDescription>>();
        public final HashMap<String, HashMap<String, InverseDescription>> inverseMethods =
                new HashMap<String, HashMap<String, InverseDescription>>();

        @Override
        public Intermediate upgrade() {
            IntermediateV3 v3 = new IntermediateV3();
            v3.adapterMethods.putAll(adapterMethods);
            v3.renamedMethods.putAll(renamedMethods);
            v3.conversionMethods.putAll(conversionMethods);
            v3.untaggableTypes.putAll(untaggableTypes);
            v3.multiValueAdapters.putAll(multiValueAdapters);
            v3.inverseAdapters.putAll(inverseAdapters);
            v3.inverseMethods.putAll(inverseMethods);
            return v3.upgrade();
        }
    }

    private static class IntermediateV3 extends IntermediateV2 {
        private static final long serialVersionUID = 0xC00L;
        public final HashMap<InverseMethodDescription, String> twoWayMethods = new HashMap<>();

        @Override
        public Intermediate upgrade() {
            return this;
        }
    }

    public static class AdapterSetter extends SetterCall {
        final MethodDescription mAdapter;
        final ModelClass mParameterType;

        public AdapterSetter(MethodDescription adapter, ModelClass parameterType) {
            mAdapter = adapter;
            mParameterType = parameterType;
        }

        @Override
        public String toJavaInternal(String componentExpression, String viewExpression,
                String valueExpression) {
            return createAdapterCall(mAdapter, componentExpression,
                    viewExpression, mCastString + valueExpression);
        }

        @Override
        protected String toJavaInternal(String componentExpression, String viewExpression,
                String oldValue, String valueExpression) {
            return createAdapterCall(mAdapter, componentExpression,
                    viewExpression, mCastString + oldValue, mCastString + valueExpression);
        }

        @Override
        public int getMinApi() {
            return 1;
        }

        @Override
        public boolean requiresOldValue() {
            return mAdapter.requiresOldValue;
        }

        @Override
        public ModelClass[] getParameterTypes() {
            return new ModelClass[] { mParameterType };
        }

        @Override
        public String getBindingAdapterInstanceClass() {
            return mAdapter.isStatic ? null : mAdapter.type;
        }

        @Override
        public String getDescription() {
            return mAdapter.type + "." + mAdapter.method;
        }
    }

    public static class ModelMethodSetter extends SetterCall {
        final ModelMethod mModelMethod;

        public ModelMethodSetter(ModelMethod modelMethod) {
            mModelMethod = modelMethod;
        }

        @Override
        public String toJavaInternal(String componentExpression, String viewExpression,
                String valueExpression) {
            return viewExpression + "." + mModelMethod.getName() + "(" + mCastString +
                    valueExpression + ")";
        }

        @Override
        protected String toJavaInternal(String componentExpression, String viewExpression,
                String oldValue, String valueExpression) {
            return viewExpression + "." + mModelMethod.getName() + "(" +
                    mCastString + oldValue + ", " + mCastString + valueExpression + ")";
        }

        @Override
        public int getMinApi() {
            return mModelMethod.getMinApi();
        }

        @Override
        public boolean requiresOldValue() {
            return mModelMethod.getParameterTypes().length == 3;
        }

        @Override
        public ModelClass[] getParameterTypes() {
            return new ModelClass[] { mModelMethod.getParameterTypes()[0] };
        }

        @Override
        public String getBindingAdapterInstanceClass() {
            return null;
        }

        @Override
        public String getDescription() {
            String args = Arrays.stream(mModelMethod.getParameterTypes())
                    .map(param -> param.toJavaCode())
                    .collect(Collectors.joining(", "));
            return mModelMethod.getReceiverType().toJavaCode() + '.' +
                    mModelMethod.getName() + '(' + args + ')';

        }
    }

    public interface BindingSetterCall {
        String toJava(String componentExpression, String viewExpression,
                String... valueExpressions);

        int getMinApi();

        boolean requiresOldValue();

        ModelClass[] getParameterTypes();

        String getBindingAdapterInstanceClass();

        // A description of the setter method to be used in an error message
        String getDescription();
    }

    public static abstract class SetterCall implements BindingSetterCall {
        private MethodDescription mConverter;
        protected String mCastString = "";

        public SetterCall() {
        }

        public void setConverter(MethodDescription converter) {
            mConverter = converter;
        }

        protected abstract String toJavaInternal(String componentExpression, String viewExpression,
                String converted);

        protected abstract String toJavaInternal(String componentExpression, String viewExpression,
                String oldValue, String converted);

        @Override
        public final String toJava(String componentExpression, String viewExpression,
                String... valueExpression) {
            Preconditions.check(valueExpression.length == 2, "value expressions size must be 2");
            if (requiresOldValue()) {
                return toJavaInternal(componentExpression, viewExpression,
                        convertValue(valueExpression[0]), convertValue(valueExpression[1]));
            } else {
                return toJavaInternal(componentExpression, viewExpression,
                        convertValue(valueExpression[1]));
            }
        }

        protected String convertValue(String valueExpression) {
            return mConverter == null ? valueExpression :
                    mConverter.type + "." + mConverter.method + "(" + valueExpression + ")";
        }

        @Override
        abstract public int getMinApi();

        public void setCast(ModelClass castTo) {
            mCastString = "(" + castTo.toJavaCode() + ") ";
        }
    }

    public static class MultiAttributeSetter implements BindingSetterCall {
        public final String[] attributes;
        private final MethodDescription mAdapter;
        private final MethodDescription[] mConverters;
        private final String[] mCasts;
        private final MultiValueAdapterKey mKey;
        private final boolean[] mSupplied;

        public MultiAttributeSetter(MultiValueAdapterKey key, boolean[] supplied,
                MethodDescription adapter, MethodDescription[] converters, String[] casts) {
            Preconditions.check(converters != null &&
                    converters.length == key.attributes.length &&
                    casts != null && casts.length == key.attributes.length &&
                    supplied.length == key.attributes.length,
                    "invalid arguments to create multi attr setter");
            this.mAdapter = adapter;
            this.mConverters = converters;
            this.mCasts = casts;
            this.mKey = key;
            this.mSupplied = supplied;
            if (key.requireAll) {
                this.attributes = key.attributes;
            } else {
                int numSupplied = 0;
                for (int i = 0; i < mKey.attributes.length; i++) {
                    if (supplied[i]) {
                        numSupplied++;
                    }
                }
                if (numSupplied == key.attributes.length) {
                    this.attributes = key.attributes;
                } else {
                    this.attributes = new String[numSupplied];
                    int attrIndex = 0;
                    for (int i = 0; i < key.attributes.length; i++) {
                        if (supplied[i]) {
                            attributes[attrIndex++] = key.attributes[i];
                        }
                    }
                }
            }
        }

        @Override
        public final String toJava(String componentExpression, String viewExpression,
                String... valueExpressions) {
            Preconditions.check(valueExpressions.length == attributes.length * 2,
                    "MultiAttributeSetter needs %s items, received %s",
                    Arrays.toString(attributes), Arrays.toString(valueExpressions));
            final int numAttrs = mKey.attributes.length;
            String[] args = new String[numAttrs + (requiresOldValue() ? numAttrs : 0)];

            final int startIndex = mAdapter.requiresOldValue ? 0 : numAttrs;
            int attrIndex = mAdapter.requiresOldValue ? 0 : attributes.length;
            final ModelAnalyzer modelAnalyzer = ModelAnalyzer.getInstance();
            StringBuilder argBuilder = new StringBuilder();
            final int endIndex = numAttrs * 2;
            for (int i = startIndex; i < endIndex; i++) {
                argBuilder.setLength(0);
                if (!mSupplied[i % numAttrs]) {
                    final String paramType = mKey.parameterTypes[i % numAttrs];
                    final String defaultValue = modelAnalyzer.getDefaultValue(paramType);
                    argBuilder.append('(')
                            .append(paramType)
                            .append(')')
                            .append(defaultValue);
                } else {
                    if (mConverters[i % numAttrs] != null) {
                        final MethodDescription converter = mConverters[i % numAttrs];
                        argBuilder.append(converter.type)
                                .append('.')
                                .append(converter.method)
                                .append('(')
                                .append(valueExpressions[attrIndex])
                                .append(')');
                    } else {
                        if (mCasts[i % numAttrs] != null) {
                            argBuilder.append('(')
                                    .append(mCasts[i % numAttrs])
                                    .append(')');
                        }
                        argBuilder.append(valueExpressions[attrIndex]);
                    }
                    attrIndex++;
                }
                args[i - startIndex] = argBuilder.toString();
            }
            return createAdapterCall(mAdapter, componentExpression, viewExpression, args);
        }

        @Override
        public int getMinApi() {
            return 1;
        }

        @Override
        public boolean requiresOldValue() {
            return mAdapter.requiresOldValue;
        }

        @Override
        public ModelClass[] getParameterTypes() {
            ModelClass[] parameters = new ModelClass[attributes.length];
            String[] paramTypeStrings = mKey.parameterTypes;
            ModelAnalyzer modelAnalyzer = ModelAnalyzer.getInstance();
            int attrIndex = 0;
            for (int i = 0; i < mKey.attributes.length; i++) {
                if (mSupplied[i]) {
                    parameters[attrIndex++] = modelAnalyzer.findClass(paramTypeStrings[i], null);
                }
            }
            return parameters;
        }

        @Override
        public String getBindingAdapterInstanceClass() {
            return mAdapter.isStatic ? null : mAdapter.type;
        }

        @Override
        public String toString() {
            return "MultiAttributeSetter{" +
                    "attributes=" + Arrays.toString(attributes) +
                    ", mAdapter=" + mAdapter +
                    ", mConverters=" + Arrays.toString(mConverters) +
                    ", mCasts=" + Arrays.toString(mCasts) +
                    ", mKey=" + mKey +
                    '}';
        }

        @Override
        public String getDescription() {
            return mAdapter.type + "." + mAdapter.method;
        }
    }

    public static class ViewDataBindingEventSetter implements BindingSetterCall {

        public ViewDataBindingEventSetter() {
        }

        @Override
        public String toJava(String componentExpression, String viewExpression,
                String... valueExpressions) {
            return "setBindingInverseListener(" + viewExpression + ", " +
                    valueExpressions[0] + ", " + valueExpressions[1] + ")";
        }

        @Override
        public int getMinApi() {
            return 0;
        }

        @Override
        public boolean requiresOldValue() {
            return true;
        }

        @Override
        public ModelClass[] getParameterTypes() {
            ModelClass[] parameterTypes = new ModelClass[1];
            parameterTypes[0] = ModelAnalyzer.getInstance().findClass(
                    "android.databinding.ViewDataBinder.PropertyChangedInverseListener", null);
            return parameterTypes;
        }

        @Override
        public String getBindingAdapterInstanceClass() {
            return null;
        }

        @Override
        public String getDescription() {
            return "ViewDataBinding.setBindingInverseListener";
        }
    }

    public interface BindingGetterCall {
        String toJava(String componentExpression, String viewExpression);

        String getGetterType();

        int getMinApi();

        String getBindingAdapterInstanceClass();

        void setBindingAdapterCall(String method);

        BindingSetterCall getEvent();

        String getEventAttribute();
    }

    public static class ViewDataBindingGetterCall implements BindingGetterCall {
        private final String mGetter;
        private final BindingSetterCall mEventSetter;
        private final String mAttribute;
        private final ModelClass mBindingClass;

        public ViewDataBindingGetterCall(ModelClass bindingClass, String attribute) {
            final int colonIndex = attribute.indexOf(':');
            mAttribute = attribute.substring(colonIndex + 1);
            mGetter = "get" + StringUtils.capitalize(mAttribute);
            mEventSetter = new ViewDataBindingEventSetter();
            mBindingClass = bindingClass;
        }

        @Override
        public String toJava(String componentExpression, String viewExpression) {
            return viewExpression + "." + mGetter + "()";
        }

        @Override
        public String getGetterType() {
            return mBindingClass.findInstanceGetter(mGetter).getReturnType().toJavaCode();
        }

        @Override
        public int getMinApi() {
            return 0;
        }

        @Override
        public String getBindingAdapterInstanceClass() {
            return null;
        }

        @Override
        public void setBindingAdapterCall(String method) {
        }

        @Override
        public BindingSetterCall getEvent() {
            return mEventSetter;
        }

        @Override
        public String getEventAttribute() {
            return mAttribute;
        }
    }

    public static class ViewGetterCall implements BindingGetterCall {
        private final InverseDescription mInverseDescription;
        private final BindingSetterCall mEventCall;
        private final ModelMethod mMethod;

        public ViewGetterCall(InverseDescription inverseDescription, ModelMethod method,
                BindingSetterCall eventCall) {
            mInverseDescription = inverseDescription;
            mEventCall = eventCall;
            mMethod = method;
        }

        @Override
        public BindingSetterCall getEvent() {
            return mEventCall;
        }

        @Override
        public String getEventAttribute() {
            return mInverseDescription.event;
        }

        @Override
        public String toJava(String componentExpression, String viewExpression) {
            return viewExpression + "." + mMethod.getName() + "()";
        }

        @Override
        public String getGetterType() {
            return mMethod.getReturnType().toJavaCode();
        }

        @Override
        public int getMinApi() {
            return mMethod.getMinApi();
        }

        @Override
        public String getBindingAdapterInstanceClass() {
            return null;
        }

        @Override
        public void setBindingAdapterCall(String method) {
        }
    }

    public static class AdapterGetter implements BindingGetterCall {
        private final InverseDescription mInverseDescription;
        private String mBindingAdapterCall;
        private final BindingSetterCall mEventCall;
        private final String mGetterType;

        public AdapterGetter(InverseDescription description, BindingSetterCall eventCall,
                String getterType) {
            mInverseDescription = description;
            mEventCall = eventCall;
            mGetterType = getterType;
        }

        @Override
        public String getGetterType() {
            return mGetterType;
        }

        @Override
        public String toJava(String componentExpression, String viewExpression) {
            StringBuilder sb = new StringBuilder();

            if (mInverseDescription.isStatic) {
                sb.append(mInverseDescription.type);
            } else {
                sb.append(componentExpression).append('.').append(mBindingAdapterCall);
            }
            sb.append('.').append(mInverseDescription.method).append('(');
            if (mInverseDescription.componentClass != null) {
                if (!"DataBindingComponent".equals(mInverseDescription.componentClass)) {
                    sb.append('(').append(mInverseDescription.componentClass).append(") ");
                }
                sb.append(componentExpression).append(", ");
            }
            sb.append(viewExpression).append(')');
            return sb.toString();
        }

        @Override
        public int getMinApi() {
            return 1;
        }

        @Override
        public String getBindingAdapterInstanceClass() {
            return mInverseDescription.isStatic ? null : mInverseDescription.type;
        }

        @Override
        public void setBindingAdapterCall(String method) {
            mBindingAdapterCall = method;
        }

        @Override
        public BindingSetterCall getEvent() {
            return mEventCall;
        }

        @Override
        public String getEventAttribute() {
            return mInverseDescription.event;
        }
    }

    private static class InverseMethod {
        public BindingGetterCall call;
        public ModelClass returnType;
        public ModelClass viewType;

        public InverseMethod(BindingGetterCall call, ModelClass returnType, ModelClass viewType) {
            this.call = call;
            this.returnType = returnType;
            this.viewType = viewType;
        }
    }
}
