package polyglot;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.ExecutionException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.util.concurrent.ListenableFuture;
import com.google.protobuf.Message;

import io.grpc.Channel;
import io.grpc.netty.NegotiationType;
import io.grpc.netty.NettyChannelBuilder;
import polyglot.HelloProto.HelloRequest;
import polyglot.HelloProto.HelloResponse;
import polyglot.HelloServiceGrpc.HelloServiceBlockingStub;
import polyglot.HelloServiceGrpc.HelloServiceFutureStub;

public class Main {
  private static final Logger logger = LoggerFactory.getLogger(Main.class);

  private static final int REMOTE_PORT = 12345;
  private static final String REMOTE_HOST = "localhost";
  private static final HelloRequest REQUEST = HelloRequest.newBuilder()
      .setRecipient("Polyglot")
      .build();

  private static Channel newChannel() {
    return NettyChannelBuilder.forAddress(REMOTE_HOST, REMOTE_PORT)
        .negotiationType(NegotiationType.PLAINTEXT)
        .build();
  }

  public static void main(String[] args) throws
      IOException,
      InterruptedException,
      ClassNotFoundException,
      IllegalArgumentException,
      IllegalAccessException, NoSuchMethodException, SecurityException, InvocationTargetException {
    logger.info("Starting grpc client to [" + REMOTE_HOST + ":" + REMOTE_PORT + "]");

    // Open a regular stub..
    HelloServiceBlockingStub helloStub = HelloServiceGrpc.newBlockingStub(newChannel());
    HelloResponse helloResponse = helloStub.sayHello(HelloRequest.newBuilder()
        .setRecipient("Polyglot")
        .build());
    logger.info("Got response from blocking: " + helloResponse);

    // Open a future stub.
    HelloServiceFutureStub helloFutureStub = HelloServiceGrpc.newFutureStub(newChannel());
    ListenableFuture<HelloResponse> responseFuture = helloFutureStub.sayHello(REQUEST);
    try {
      logger.info("Got response with future: " + responseFuture.get());
    } catch (ExecutionException e) {
      logger.error("Failed to make rpc", e);
    }

    // ********** Scratch space below *************

    String className = "polyglot.HelloServiceGrpc";
    String serviceName = "polyglot.HelloService";
    String methodName = "SayHello";
    String generatedMethodName = "sayHello";

    logger.info("Creating grpc client");
    Class<?> grpcClass = Main.class.getClassLoader().loadClass(className);
    GrpcClient client =
        GrpcClient.forGrpcClass(grpcClass, generatedMethodName, REMOTE_HOST, REMOTE_PORT);
    logger.info("Making generic call");
    ListenableFuture<Message> genericResponseFuture = client.call(REQUEST);
    try {
      logger.info("Got response with future: " + genericResponseFuture.get());
    } catch (ExecutionException e) {
      logger.error("Failed to make rpc", e);
    }

//    // Parse the request type.
//    GeneratedMessage.Builder<?> builder =
//        (Builder<?>) requestType.getMethod("newBuilder").invoke(null /* obj */);
//    String textFormatProto = "";
//    TextFormat.getParser().merge(textFormatProto, builder);
//    Message requestMessage = builder.build();
//
//    // Opening stubs.
//    Object reflectiveHelloStub = helloServiceGrpcClass
//        .getMethod("newStub", io.grpc.Channel.class)
//        .invoke(null /* obj */, newChannel());
//    Method sayHelloMethod = reflectiveHelloStub.getClass()
//        .getMethod(generatedMethodName, requestType, StreamObserver.class);
//    //sayHelloMethod.invoke(reflectiveHelloStub, requestMessage);
  }
}

@@ -16,88 +16,8 @@
 t;%0A%0A
-import java.io.IOException;%0Aimport java.lang.reflect.InvocationTargetException;%0A
 impo
@@ -205,16 +205,25 @@
 rotobuf.
+Generated
 Message;
@@ -227,1381 +227,614 @@
 ge;%0A
-%0A
 import 
-io.grpc.Channel;%0Aimport io.grpc.netty.NegotiationType;%0Aimport io.grpc.netty.NettyChannelBuilder;%0Aimport polyglot.HelloProto.HelloRequest;%0Aimport polyglot.HelloProto.HelloResponse;%0Aimport polyglot.HelloServiceGrpc.HelloServiceBlockingStub;%0Aimport polyglot.HelloServiceGrpc.HelloServiceFutureStub;%0A%0Apublic class Main %7B%0A  private static final Logger logger = LoggerFactory.getLogger(Main.class);%0A%0A  private static final int REMOTE_PORT = 12345;%0A  private static final String REMOTE_HOST = %22localhost%22;%0A  private static final HelloRequest REQUEST = HelloRequest.newBuilder()%0A      .setRecipient(%22Polyglot%22)%0A      .build();%0A%0A  private static Channel newChannel() %7B%0A    return NettyChannelBuilder.forAddress(REMOTE_HOST, REMOTE_PORT)%0A        .negotiationType(NegotiationType.PLAINTEXT)%0A        .build();%0A  %7D%0A%0A  public static void main(String%5B%5D args) throws%0A      IOException,%0A      InterruptedException,%0A      ClassNotFoundException,%0A      IllegalArgumentException,%0A      IllegalAccessException, NoSuchMethodException, SecurityException, InvocationTargetException %7B%0A    logger.info(%22Starting grpc client to %5B%22 + REMOTE_HOST + %22:%22 + REMOTE_PORT + %22%5D%22);%0A%0A    // Open a regular stub..%0A    HelloServiceBlockingStub helloStub = HelloServiceGrpc.newBlockingStub(newChannel());%0A    HelloResponse helloResponse = helloStub.sayHello(HelloRequest.newBuilder()%0A        .setR
+com.google.protobuf.Message;%0Aimport com.google.protobuf.TextFormat;%0A%0Aimport polyglot.HelloProto.HelloRequest;%0A%0Apublic class Main %7B%0A  private static final Logger logger = LoggerFactory.getLogger(Main.class);%0A%0A  private static final int REMOTE_PORT = 12345;%0A  private static final String REMOTE_HOST = %22localhost%22;%0A%0A  public static void main(String%5B%5D args) throws Exception %7B%0A    String className = %22polyglot.HelloServiceGrpc%22;%0A    String serviceName = %22polyglot.HelloService%22;%0A    String methodName = %22SayHello%22;%0A    String generatedMethodName = %22sayHello%22;%0A%0A    String textFormatRequest = %22r
 ecipient
 (%22Po
@@ -829,17 +829,19 @@
 ecipient
-(
+: %5C
 %22Polyglo
@@ -845,707 +845,363 @@
 glot
-%22)%0A        .build())
+%5C%22%22
 ;%0A
+%0A
     
-logger.info(%22Got response from blocking: %22 + helloResponse);%0A%0A    // Open a future stub.%0A    HelloServiceFutureStub helloFutureStub = HelloServiceGrpc.newFutureStub(newChannel());%0A    ListenableFuture%3CHelloResponse%3E responseFuture = helloFutureStub.sayHello(REQUEST);%0A    try %7B%0A      logger.info(%22Got response with future: %22 + responseFuture.get());%0A    %7D catch (ExecutionException e) %7B%0A      logger.error(%22Failed to make rpc%22, e);%0A    %7D%0A%0A    // ********** Scratch space below *************%0A%0A    String className = %22polyglot.HelloServiceGrpc%22;%0A    String serviceName = %22polyglot.HelloService%22;%0A    String methodName = %22SayHello%22;%0A    String generatedMethodName = %22sayHello%22
+// Parse the request type.%0A    Class%3C? extends GeneratedMessage%3E requestType = HelloRequest.class;%0A    GeneratedMessage.Builder%3C?%3E builder =%0A        (GeneratedMessage.Builder%3C?%3E) requestType.getMethod(%22newBuilder%22).invoke(null /* obj */);%0A    TextFormat.getParser().merge(textFormatRequest, builder);%0A    Message requestMessage = builder.build()
 ;%0A%0A 
@@ -1540,15 +1540,22 @@
 all(
-REQUEST
+requestMessage
 );%0A 
@@ -1733,709 +1733,8 @@
    %7D
-%0A%0A//    // Parse the request type.%0A//    GeneratedMessage.Builder%3C?%3E builder =%0A//        (Builder%3C?%3E) requestType.getMethod(%22newBuilder%22).invoke(null /* obj */);%0A//    String textFormatProto = %22%22;%0A//    TextFormat.getParser().merge(textFormatProto, builder);%0A//    Message requestMessage = builder.build();%0A//%0A//    // Opening stubs.%0A//    Object reflectiveHelloStub = helloServiceGrpcClass%0A//        .getMethod(%22newStub%22, io.grpc.Channel.class)%0A//        .invoke(null /* obj */, newChannel());%0A//    Method sayHelloMethod = reflectiveHelloStub.getClass()%0A//        .getMethod(generatedMethodName, requestType, StreamObserver.class);%0A//    //sayHelloMethod.invoke(reflectiveHelloStub, requestMessage);
 %0A  %7D

Clean up the main class, add parsing of the request proto.