// Path: android/tweakr/src/main/java/com/google/tweakr/collections/FieldMap.java
// public class FieldMap<K> extends MemberMap<K, Field> {
// 
//     @Override
//     protected void setValue(MemberHolder holder, Object value) throws IllegalAccessException {
//         Object target = holder.target.get();
//         holder.member.set(target, value);
//     }
// }
// 
// Path: android/tweakr/src/main/java/com/google/tweakr/collections/MethodMap.java
// public class MethodMap<K> extends MemberMap<K, Method> {
// 
//     @Override
//     protected void setValue(MemberHolder holder, Object value) throws InvocationTargetException, IllegalAccessException {
//         Object target = holder.target.get();
// 
//         if (holder.member.getParameterTypes().length > 0) {
//             holder.member.invoke(target, value);
//         } else {
//             holder.member.invoke(target);
//         }
//     }
// }
// 
// Path: android/tweakr/src/main/java/com/google/tweakr/types/DefaultValueTypeConverter.java
// public class DefaultValueTypeConverter implements ValueTypeConverter {
// 
//     @Override
//     public ValueType getType(Class<?> fieldType) {
//         if (fieldType.isArray()) {
//             return new ArrayValueType(getType(fieldType.getComponentType()));
//         }
// 
//         if (fieldType == float.class || fieldType == double.class || fieldType == Float.class || fieldType == Double.class) {
//             return new PrimitiveValueType(PrimitiveValueType.TYPE_FLOAT);
//         } else if (fieldType == int.class || fieldType == long.class || fieldType == Integer.class || fieldType == Long.class) {
//             return new PrimitiveValueType(PrimitiveValueType.TYPE_INT);
//         } else if (fieldType == boolean.class || fieldType == Boolean.class) {
//             return new PrimitiveValueType(PrimitiveValueType.TYPE_BOOLEAN);
//         } else if (fieldType.isAssignableFrom(String.class)) {
//             return new PrimitiveValueType(PrimitiveValueType.TYPE_STRING);
//         } else if (fieldType.isEnum()) {
//             return new EnumValueType(fieldType);
//         }
// 
//         return new PrimitiveValueType(PrimitiveValueType.TYPE_UNKNOWN);
//     }
// }
// 
// Path: android/tweakr/src/main/java/com/google/tweakr/types/ValueType.java
// public interface ValueType {
//     /**
//      * Simple name of the type. Used to select an appropriate UI.
//      */
//     String getName();
// 
//     /**
//      * A default value if one cannot be determined.
//      */
//     Object getDefault();
// 
//     /**
//      * Safely convert a value from Firebase into the correct type.
//      */
//     Object convert(Object newValue);
// 
//     /**
//      * For enum fields or other fields you want to restrict to only certain choices.
//      *
//      * @return An array of String representations of all possible values to choose from.
//      */
//     default List<String> getPossibleValues() {
//         return null;
//     }
// }
// 
// Path: android/tweakr/src/main/java/com/google/tweakr/types/ValueTypeConverter.java
// public interface ValueTypeConverter {
// 
//     ValueType getType(Class<?> fieldType);
// }
// 
// Path: android/tweakr/src/main/java/com/google/tweakr/types/VoidValueType.java
// public class VoidValueType implements ValueType {
// 
//     @Override
//     public String getName() {
//         return "void";
//     }
// 
//     @Override
//     public Object getDefault() {
//         return null;
//     }
// 
//     @Override
//     public Object convert(Object newValue) {
//         return null;
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) return true;
//         if (o == null || getClass() != o.getClass()) return false;
//         ValueType that = (ValueType) o;
//         return getName().equals(that.getName());
//     }
// 
//     @Override
//     public int hashCode() {
//         return Objects.hash(getName());
//     }
// }


import static com.google.tweakr.TweakrRepo.FIELD_SEPARATOR;
import android.util.Log;
import androidx.annotation.NonNull;
import com.google.tweakr.annotations.Tweak;
import com.google.tweakr.collections.FieldMap;
import com.google.tweakr.collections.MethodMap;
import com.google.tweakr.types.DefaultValueTypeConverter;
import com.google.tweakr.types.ValueType;
import com.google.tweakr.types.ValueTypeConverter;
import com.google.tweakr.types.VoidValueType;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
                return annotation.valueType().newInstance();
            } catch (IllegalAccessException|InstantiationException e) {
                Log.e(TAG, "Could not create custom ValueType", e);
            }
        }

        return null;
    }

    @NonNull
    private String buildName(Object target, Member field, String targetPrefix) {
        String name = field.getName();
        String targetClass = target.getClass().getSimpleName();
        if (!TextUtils.isEmpty(targetClass)) {
            name = targetClass + FIELD_SEPARATOR + name;
        }
        if (!TextUtils.isEmpty(targetPrefix)) {
            name = targetPrefix + FIELD_SEPARATOR + name;
        }
        return name;
    }

    private void registerMethod(Object target, Method method, String name, Tweak annotation) {
        methods.add(name, target, method);

        // Register with firebase.
        ValueType valueType = getCustomValueType(annotation);
        if (valueType == null) {
            Class<?>[] parameterTypes = method.getParameterTypes();
            valueType = parameterTypes.length > 0 ? typeConverter.getType(parameterTypes[0])
// Path: android/tweakr/src/main/java/com/google/tweakr/collections/FieldMap.java
// public class FieldMap<K> extends MemberMap<K, Field> {
// 
//     @Override
//     protected void setValue(MemberHolder holder, Object value) throws IllegalAccessException {
//         Object target = holder.target.get();
//         holder.member.set(target, value);
//     }
// }
// 
// Path: android/tweakr/src/main/java/com/google/tweakr/collections/MethodMap.java
// public class MethodMap<K> extends MemberMap<K, Method> {
// 
//     @Override
//     protected void setValue(MemberHolder holder, Object value) throws InvocationTargetException, IllegalAccessException {
//         Object target = holder.target.get();
// 
//         if (holder.member.getParameterTypes().length > 0) {
//             holder.member.invoke(target, value);
//         } else {
//             holder.member.invoke(target);
//         }
//     }
// }
// 
// Path: android/tweakr/src/main/java/com/google/tweakr/types/DefaultValueTypeConverter.java
// public class DefaultValueTypeConverter implements ValueTypeConverter {
// 
//     @Override
//     public ValueType getType(Class<?> fieldType) {
//         if (fieldType.isArray()) {
//             return new ArrayValueType(getType(fieldType.getComponentType()));
//         }
// 
//         if (fieldType == float.class || fieldType == double.class || fieldType == Float.class || fieldType == Double.class) {
//             return new PrimitiveValueType(PrimitiveValueType.TYPE_FLOAT);
//         } else if (fieldType == int.class || fieldType == long.class || fieldType == Integer.class || fieldType == Long.class) {
//             return new PrimitiveValueType(PrimitiveValueType.TYPE_INT);
//         } else if (fieldType == boolean.class || fieldType == Boolean.class) {
//             return new PrimitiveValueType(PrimitiveValueType.TYPE_BOOLEAN);
//         } else if (fieldType.isAssignableFrom(String.class)) {
//             return new PrimitiveValueType(PrimitiveValueType.TYPE_STRING);
//         } else if (fieldType.isEnum()) {
//             return new EnumValueType(fieldType);
//         }
// 
//         return new PrimitiveValueType(PrimitiveValueType.TYPE_UNKNOWN);
//     }
// }
// 
// Path: android/tweakr/src/main/java/com/google/tweakr/types/ValueType.java
// public interface ValueType {
//     /**
//      * Simple name of the type. Used to select an appropriate UI.
//      */
//     String getName();
// 
//     /**
//      * A default value if one cannot be determined.
//      */
//     Object getDefault();
// 
//     /**
//      * Safely convert a value from Firebase into the correct type.
//      */
//     Object convert(Object newValue);
// 
//     /**
//      * For enum fields or other fields you want to restrict to only certain choices.
//      *
//      * @return An array of String representations of all possible values to choose from.
//      */
//     default List<String> getPossibleValues() {
//         return null;
//     }
// }
// 
// Path: android/tweakr/src/main/java/com/google/tweakr/types/ValueTypeConverter.java
// public interface ValueTypeConverter {
// 
//     ValueType getType(Class<?> fieldType);
// }
// 
// Path: android/tweakr/src/main/java/com/google/tweakr/types/VoidValueType.java
// public class VoidValueType implements ValueType {
// 
//     @Override
//     public String getName() {
//         return "void";
//     }
// 
//     @Override
//     public Object getDefault() {
//         return null;
//     }
// 
//     @Override
//     public Object convert(Object newValue) {
//         return null;
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) return true;
//         if (o == null || getClass() != o.getClass()) return false;
//         ValueType that = (ValueType) o;
//         return getName().equals(that.getName());
//     }
// 
//     @Override
//     public int hashCode() {
//         return Objects.hash(getName());
//     }
// }


// Path: android/tweakr/src/main/java/com/google/tweakr/TweakrRegistry.java
import static com.google.tweakr.TweakrRepo.FIELD_SEPARATOR;
import android.util.Log;
import androidx.annotation.NonNull;
import com.google.tweakr.annotations.Tweak;
import com.google.tweakr.collections.FieldMap;
import com.google.tweakr.collections.MethodMap;
import com.google.tweakr.types.DefaultValueTypeConverter;
import com.google.tweakr.types.ValueType;
import com.google.tweakr.types.ValueTypeConverter;
import com.google.tweakr.types.VoidValueType;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

                return annotation.valueType().newInstance();
            } catch (IllegalAccessException|InstantiationException e) {
                Log.e(TAG, "Could not create custom ValueType", e);
            }
        }

        return null;
    }

    @NonNull
    private String buildName(Object target, Member field, String targetPrefix) {
        String name = field.getName();
        String targetClass = target.getClass().getSimpleName();
        if (!TextUtils.isEmpty(targetClass)) {
            name = targetClass + FIELD_SEPARATOR + name;
        }
        if (!TextUtils.isEmpty(targetPrefix)) {
            name = targetPrefix + FIELD_SEPARATOR + name;
        }
        return name;
    }

    private void registerMethod(Object target, Method method, String name, Tweak annotation) {
        methods.add(name, target, method);

        // Register with firebase.
        ValueType valueType = getCustomValueType(annotation);
        if (valueType == null) {
            Class<?>[] parameterTypes = method.getParameterTypes();
            valueType = parameterTypes.length > 0 ? typeConverter.getType(parameterTypes[0])
                    : new VoidValueType();