package com.vimeo.networking;

import org.jetbrains.annotations.NotNull;

import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Type;

import okhttp3.ResponseBody;
import retrofit2.Converter;
import retrofit2.Retrofit;

/**
 * This is a converter factory that allows you to specify different converters to use for each request.
 * This was taken from https://stackoverflow.com/questions/40824122/android-retrofit-2-multiple-converters-gson-simplexml-error.
 * It provides two annotations - Gson and Moshi that should be used on a Retrofit request service to specify which
 * serialization framework to use. If a annotation is not specified, Gson will be used.
 */
public final class AnnotatedConverterFactory extends Converter.Factory {

    /**
     * Annotate a method to specify the type of serialization to use. Gson or Moshi.
     */
    @Retention(RetentionPolicy.RUNTIME)
    @interface Serializer {

        @NotNull
        ConverterType converter();

    }

    /**
     * Different types of converter that can be specified in the serializer annotation.
     */
    enum ConverterType {
        GSON,
        MOSHI
    }

    /**
     * Gson converter.
     */
    @NotNull
    private final Converter.Factory gsonFactory;

    /**
     * Moshi converter.
     */
    @NotNull
    private final Converter.Factory moshiFactory;

    /**
     * Specify all serialization converters that can be used in the SDK. The type of serialization
     * framework to use could be chosen by specifying it in the serializer annotation.
     *
     * @param gsonFactory  Gson converter factory.
     * @param moshiFactory Moshi converter factory.
     */
    AnnotatedConverterFactory(@NotNull final Converter.Factory gsonFactory,
                              @NotNull final Converter.Factory moshiFactory) {
        this.gsonFactory = gsonFactory;
        this.moshiFactory = moshiFactory;
    }

    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(@NotNull final Type type,
                                                            @NotNull final Annotation[] annotations,
                                                            @NotNull final Retrofit retrofit) {
        Converter.Factory converterFactory = gsonFactory;

        for (final Annotation annotation : annotations) {
            if (annotation instanceof Serializer) {
                final ConverterType converterType = ((Serializer) annotation).converter();
                if (converterType == ConverterType.MOSHI) {
                    converterFactory = moshiFactory;
                    break;
                }
            }
        }
        return converterFactory.responseBodyConverter(type, annotations, retrofit);
    }

}

@@ -65,16 +65,59 @@
 NotNull;
+%0Aimport org.jetbrains.annotations.Nullable;
 %0A%0Aimport
@@ -481,16 +481,19 @@
 ken from
+%0A *
  https:/
@@ -590,19 +590,16 @@
 l-error.
-%0A *
  It prov
@@ -606,125 +606,11 @@
 ides
- two annotations - Gson and Moshi that should be used on a Retrofit request service to specify which%0A * serialization
+%0A *
  fra
@@ -2220,101 +2220,215 @@
     
-Converter.Factory converterFactory = gsonFactory;%0A%0A        for (final Annotation annotation :
+return chooseFactoryForSerializer(annotations).responseBodyConverter(type, annotations, retrofit);%0A    %7D%0A%0A    /**%0A     * Choose the %7B@link Converter.Factory%7D that will be used based on the %7B@link Serializer%7D
  ann
@@ -2438,29 +2438,31 @@
 tion
-s) %7B
+.
 %0A     
+*%0A
      
-  if (
+* @param 
 anno
@@ -2471,145 +2471,324 @@
 tion
- instanceof Serializer) %7B
+s The annotations array that may contain the %7B@link Serializer%7D annotation.
 %0A     
+*/%0A
     
-       final ConverterType converterType = ((Serializer) annotation).converter();%0A                if (
+@NotNull%0A    private Converter.Factory chooseFactoryForSerializer(@NotNull final Annotation%5B%5D annotations) %7B%0A        final Serializer serializer = findSerializerInArray(annotations);%0A        if (serializer != null && serializer.
 conv
@@ -2792,20 +2792,18 @@
 onverter
-Type
+()
  == Conv
@@ -2837,34 +2837,14 @@
     
-        converterFactory =
+return
  mos
@@ -2854,32 +2854,41 @@
 actory;%0A        
+%7D else %7B%0A
             brea
@@ -2887,13 +2887,26 @@
     
-b
 re
-ak
+turn gsonFactory
 ;%0A  
@@ -2915,124 +2915,581 @@
     
+%7D%0A
     
+%7D%0A%0A
     
-%7D
+/**
 %0A     
-       %7D%0A        %7D%0A        return converterFactory.responseBodyConverter(type, annotations, retrofit)
+* Return the %7B@link Serializer%7D annotation instance found in the array of %7B@link Annotation%7D or null if it was not%0A     * found.%0A     *%0A     * @param annotations The annotations array to search for the %7B@link Serializer%7D annotation.%0A     */%0A    @Nullable%0A    private static Serializer findSerializerInArray(@NotNull final Annotation%5B%5D annotations) %7B%0A        for (final Annotation annotation : annotations) %7B%0A            if (annotation instanceof Serializer) %7B%0A                return (Serializer) annotation;%0A            %7D%0A        %7D%0A        return null
 ;%0A  

Break apart responseBodyConverter method into smaller methods for readability