// Path: rxjava2-client/src/main/java/net/winterly/rxjersey/client/rxjava2/RxJerseyClientFeature.java
// public class RxJerseyClientFeature implements Feature {
// 
//     private Client client;
// 
//     public RxJerseyClientFeature setClient(Client client) {
//         this.client = client;
//         return this;
//     }
// 
//     @Override
//     public boolean configure(FeatureContext context) {
//         if (client == null) {
//             client = defaultClient();
//         }
// 
//         client.register(RxBodyReader.class);
//         context.register(new Binder());
// 
//         return true;
//     }
// 
//     private Client defaultClient() {
//         int cores = Runtime.getRuntime().availableProcessors();
//         ClientConfig config = new ClientConfig();
//         config.connectorProvider(new GrizzlyConnectorProvider());
//         config.property(ClientProperties.ASYNC_THREADPOOL_SIZE, cores);
//         config.register(RxFlowableInvokerProvider.class);
// 
//         return ClientBuilder.newClient(config);
//     }
// 
//     private class Binder extends RxJerseyBinder {
// 
//         @Override
//         protected void configure() {
//             bind(new RemoteResolver(
//                     getInjectionManager(),
//                     new FlowableClientMethodInvoker(),
//                     client
//             ));
// 
//             bind(client).to(Client.class);
//             /*bind(create(RemoteResolver.class));
// 
//             bind(FlowableClientMethodInvoker.class)
//                     .to(ClientMethodInvoker.class)
//                     .in(Singleton.class);
// 
//             bind(client)
//                     .named(RemoteResolver.RX_JERSEY_CLIENT_NAME)
//                     .to(Client.class);*/
//         }
//     }
// }
// 
// Path: rxjava2-server/src/main/java/net/winterly/rxjersey/server/rxjava2/CompletableRequestInterceptor.java
// public interface CompletableRequestInterceptor extends RxRequestInterceptor<Completable> {
// 
// }
// 
// Path: rxjava2-server/src/main/java/net/winterly/rxjersey/server/rxjava2/RxJerseyServerFeature.java
// public final class RxJerseyServerFeature implements Feature {
// 
//     private final List<Class<? extends CompletableRequestInterceptor>> interceptors = new LinkedList<>();
// 
//     public RxJerseyServerFeature register(Class<? extends CompletableRequestInterceptor> interceptor) {
//         interceptors.add(interceptor);
//         return this;
//     }
// 
//     @Override
//     public boolean configure(FeatureContext context) {
//         context.register(RxBodyWriter.class);
//         context.register(new Binder());
//         return true;
//     }
// 
//     private class Binder extends AbstractBinder {
// 
//         @Override
//         protected void configure() {
//             bind(MaybeInvocationHandlerProvider.class)
//                     .to(ResourceMethodInvocationHandlerProvider.class)
//                     .in(Singleton.class);
// 
//             interceptors.forEach(interceptor -> bind(interceptor)
//                     .to(CompletableRequestInterceptor.class)
//                     .in(Singleton.class)
//             );
//         }
//     }
// }


import io.dropwizard.Configuration;
import io.dropwizard.ConfiguredBundle;
import io.dropwizard.client.JerseyClientBuilder;
import io.dropwizard.client.JerseyClientConfiguration;
import io.dropwizard.jersey.setup.JerseyEnvironment;
import io.dropwizard.setup.Bootstrap;
import io.dropwizard.setup.Environment;
import net.winterly.rxjersey.client.rxjava2.RxJerseyClientFeature;
import net.winterly.rxjersey.server.rxjava2.CompletableRequestInterceptor;
import net.winterly.rxjersey.server.rxjava2.RxJerseyServerFeature;
import org.glassfish.jersey.client.rx.rxjava2.RxFlowableInvokerProvider;
import org.glassfish.jersey.grizzly.connector.GrizzlyConnectorProvider;
import javax.ws.rs.client.Client;
import java.util.function.Function;
    public void run(T configuration, Environment environment) throws Exception {
        JerseyEnvironment jersey = environment.jersey();

        JerseyClientConfiguration clientConfiguration = clientConfigurationProvider.apply(configuration);
        Client client = getClient(environment, clientConfiguration);

        rxJerseyClientFeature.setClient(client);

        jersey.register(rxJerseyServerFeature);
        jersey.register(rxJerseyClientFeature);
    }

    @Override
    public void initialize(Bootstrap<?> bootstrap) {

    }

    public RxJerseyClientFeature client() {
        return rxJerseyClientFeature;
    }

    public RxJerseyServerFeature server() {
        return rxJerseyServerFeature;
    }

    public RxJerseyBundle<T> setClientConfigurationProvider(Function<T, JerseyClientConfiguration> provider) {
        clientConfigurationProvider = provider;
        return this;
    }

// Path: rxjava2-client/src/main/java/net/winterly/rxjersey/client/rxjava2/RxJerseyClientFeature.java
// public class RxJerseyClientFeature implements Feature {
// 
//     private Client client;
// 
//     public RxJerseyClientFeature setClient(Client client) {
//         this.client = client;
//         return this;
//     }
// 
//     @Override
//     public boolean configure(FeatureContext context) {
//         if (client == null) {
//             client = defaultClient();
//         }
// 
//         client.register(RxBodyReader.class);
//         context.register(new Binder());
// 
//         return true;
//     }
// 
//     private Client defaultClient() {
//         int cores = Runtime.getRuntime().availableProcessors();
//         ClientConfig config = new ClientConfig();
//         config.connectorProvider(new GrizzlyConnectorProvider());
//         config.property(ClientProperties.ASYNC_THREADPOOL_SIZE, cores);
//         config.register(RxFlowableInvokerProvider.class);
// 
//         return ClientBuilder.newClient(config);
//     }
// 
//     private class Binder extends RxJerseyBinder {
// 
//         @Override
//         protected void configure() {
//             bind(new RemoteResolver(
//                     getInjectionManager(),
//                     new FlowableClientMethodInvoker(),
//                     client
//             ));
// 
//             bind(client).to(Client.class);
//             /*bind(create(RemoteResolver.class));
// 
//             bind(FlowableClientMethodInvoker.class)
//                     .to(ClientMethodInvoker.class)
//                     .in(Singleton.class);
// 
//             bind(client)
//                     .named(RemoteResolver.RX_JERSEY_CLIENT_NAME)
//                     .to(Client.class);*/
//         }
//     }
// }
// 
// Path: rxjava2-server/src/main/java/net/winterly/rxjersey/server/rxjava2/CompletableRequestInterceptor.java
// public interface CompletableRequestInterceptor extends RxRequestInterceptor<Completable> {
// 
// }
// 
// Path: rxjava2-server/src/main/java/net/winterly/rxjersey/server/rxjava2/RxJerseyServerFeature.java
// public final class RxJerseyServerFeature implements Feature {
// 
//     private final List<Class<? extends CompletableRequestInterceptor>> interceptors = new LinkedList<>();
// 
//     public RxJerseyServerFeature register(Class<? extends CompletableRequestInterceptor> interceptor) {
//         interceptors.add(interceptor);
//         return this;
//     }
// 
//     @Override
//     public boolean configure(FeatureContext context) {
//         context.register(RxBodyWriter.class);
//         context.register(new Binder());
//         return true;
//     }
// 
//     private class Binder extends AbstractBinder {
// 
//         @Override
//         protected void configure() {
//             bind(MaybeInvocationHandlerProvider.class)
//                     .to(ResourceMethodInvocationHandlerProvider.class)
//                     .in(Singleton.class);
// 
//             interceptors.forEach(interceptor -> bind(interceptor)
//                     .to(CompletableRequestInterceptor.class)
//                     .in(Singleton.class)
//             );
//         }
//     }
// }


// Path: dropwizard/src/main/java/net/winterly/rxjersey/dropwizard/RxJerseyBundle.java
import io.dropwizard.Configuration;
import io.dropwizard.ConfiguredBundle;
import io.dropwizard.client.JerseyClientBuilder;
import io.dropwizard.client.JerseyClientConfiguration;
import io.dropwizard.jersey.setup.JerseyEnvironment;
import io.dropwizard.setup.Bootstrap;
import io.dropwizard.setup.Environment;
import net.winterly.rxjersey.client.rxjava2.RxJerseyClientFeature;
import net.winterly.rxjersey.server.rxjava2.CompletableRequestInterceptor;
import net.winterly.rxjersey.server.rxjava2.RxJerseyServerFeature;
import org.glassfish.jersey.client.rx.rxjava2.RxFlowableInvokerProvider;
import org.glassfish.jersey.grizzly.connector.GrizzlyConnectorProvider;
import javax.ws.rs.client.Client;
import java.util.function.Function;

    public void run(T configuration, Environment environment) throws Exception {
        JerseyEnvironment jersey = environment.jersey();

        JerseyClientConfiguration clientConfiguration = clientConfigurationProvider.apply(configuration);
        Client client = getClient(environment, clientConfiguration);

        rxJerseyClientFeature.setClient(client);

        jersey.register(rxJerseyServerFeature);
        jersey.register(rxJerseyClientFeature);
    }

    @Override
    public void initialize(Bootstrap<?> bootstrap) {

    }

    public RxJerseyClientFeature client() {
        return rxJerseyClientFeature;
    }

    public RxJerseyServerFeature server() {
        return rxJerseyServerFeature;
    }

    public RxJerseyBundle<T> setClientConfigurationProvider(Function<T, JerseyClientConfiguration> provider) {
        clientConfigurationProvider = provider;
        return this;
    }

    public RxJerseyBundle<T> register(Class<? extends CompletableRequestInterceptor> interceptor) {