package SumServiceGRPC;

import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.stub.StreamObserver;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

public class Client {

    public static void main(String[] args) throws InterruptedException {

        System.out.println("Call simpleSum synchronous method:");
        synchronousSimpleSumCall();
        System.out.println("...Done!");
        System.out.println("--------------");


        System.out.println("Call simpleSum asynchronous method:");
        asynchronousSimpleSumCall();
        System.out.println("...Done!");
        System.out.println("--------------");


        System.out.println("Call repeatedSum asynchronous method:");
        asynchronousRepeatedSumCall();
        System.out.println("...Done!");
        System.out.println("--------------");


        System.out.println("Call streamSum asynchronous method:");
        asynchronousStreamSumCall();
        System.out.println("...Done!");
        System.out.println("--------------");

    }

    public static void synchronousSimpleSumCall(){
        final ManagedChannel channel = ManagedChannelBuilder.forTarget("localhost:8080").usePlaintext().build();
        SumServiceGrpc.SumServiceBlockingStub stub = SumServiceGrpc.newBlockingStub(channel);
        SumServiceOuterClass.SimpleSumRequest request = SumServiceOuterClass.SimpleSumRequest.newBuilder()
                .setA(5)
                .setB(3)
                .build();

        SumServiceOuterClass.SumServiceResponse response = stub.simpleSum(request);
        System.out.println(response.getRes()+"");
        channel.shutdown();
    }

    public static void asynchronousSimpleSumCall() throws InterruptedException {
        final ManagedChannel channel = ManagedChannelBuilder.forTarget("localhost:8080").usePlaintext().build();
        SumServiceGrpc.SumServiceStub stub = SumServiceGrpc.newStub(channel);
        SumServiceOuterClass.SimpleSumRequest request = SumServiceOuterClass.SimpleSumRequest.newBuilder()
                .setA(5)
                .setB(3)
                .build();

        stub.simpleSum(request, new StreamObserver<SumServiceOuterClass.SumServiceResponse>() {
            public void onNext(SumServiceOuterClass.SumServiceResponse response) {
                System.out.println(response.getRes()+"");
            }

            public void onError(Throwable throwable) {
                System.out.println("Error! "+throwable.getMessage());
            }

            public void onCompleted() {
                channel.shutdownNow();
            }
        });

        //you need this. otherwise the method will terminate before that answers from the server are received
        channel.awaitTermination(10, TimeUnit.SECONDS);
    }

    public static void asynchronousRepeatedSumCall() throws InterruptedException {
        final ManagedChannel channel = ManagedChannelBuilder.forTarget("localhost:8080").usePlaintext().build();
        SumServiceGrpc.SumServiceStub stub = SumServiceGrpc.newStub(channel);
        SumServiceOuterClass.RepeatedSumRequest request = SumServiceOuterClass.RepeatedSumRequest.newBuilder()
                .setN(2)
                .setT(5)
                .build();

        stub.repeatedSum(request, new StreamObserver<SumServiceOuterClass.SumServiceResponse>() {
            public void onNext(SumServiceOuterClass.SumServiceResponse response) {
                System.out.println(response.getRes()+"");
            }

            public void onError(Throwable throwable) {
                System.out.println("Error! "+throwable.getMessage());
            }

            public void onCompleted() {
                channel.shutdownNow();
            }
        });

        //You need this. otherwise the method will terminate before that answers from the server are received
        channel.awaitTermination(10, TimeUnit.SECONDS);
    }

    public static void asynchronousStreamSumCall() throws InterruptedException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        final ManagedChannel channel = ManagedChannelBuilder.forTarget("localhost:8080").usePlaintext().build();

        SumServiceGrpc.SumServiceStub stub = SumServiceGrpc.newStub(channel);

        StreamObserver<SumServiceOuterClass.SimpleSumRequest> serverStream = stub.streamSum(new StreamObserver<SumServiceOuterClass.SumServiceResponse>() {
            //We define what to do when a message from the server arrives
            public void onNext(SumServiceOuterClass.SumServiceResponse response) {
                System.out.println("Sum:"+response.getRes());
            }

            public void onError(Throwable throwable) {
            }

            public void onCompleted() {
            }
        });


        while(true){
            String input_numbers = null;
            try {
                input_numbers = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }

            if(input_numbers.equals("quit")){
                serverStream.onCompleted();
                break;
            }

            String[] split = input_numbers.split(" ");
            int a = Integer.parseInt(split[0]);
            int b = Integer.parseInt(split[1]);

            serverStream.onNext(SumServiceOuterClass.SimpleSumRequest.newBuilder()
                    .setA(a)
                    .setB(b)
                    .build());
        }
    }
}




