package org.example;

import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Main {

    private static final Logger logger = Logger.getLogger(Main.class.getName());

    private static final Map<String, Object> CONFIG_A = Map.of("methodConfig",
        List.of(
            Map.of(
                "name", List.of(Map.of()),
                "timeout", "0.01s",
                "retryPolicy", Map.of(
                    "maxAttempts", 5D,
                    "initialBackoff", "0.002s",
                    "maxBackoff", "30s",
                    "backoffMultiplier", 1D,
                    "retryableStatusCodes", List.of("ABORTED")
                )
            )
        ));

    private static final Map<String, Object> CONFIG_B = Map.of("methodConfig",
        List.of(
            Map.of(
                "name", List.of(Map.of()),
                "timeout", "0.006s",
                "retryPolicy", Map.of(
                    "maxAttempts", 5D,
                    "initialBackoff", "0.001s",
                    "maxBackoff", "30s",
                    "backoffMultiplier", 1D,
                    "retryableStatusCodes", List.of("ABORTED")
                )
            )
        ));


    public static void main(String[] args) throws IOException {
        ServerStuck serverStuck = new ServerStuck();
        serverStuck.start();

        ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 50051)
            .usePlaintext()
            .enableRetry()
            .maxRetryAttempts(6)
            .defaultServiceConfig(CONFIG_B)
            .build();

        ClientStuck clientStuck = new ClientStuck(channel);

        while (true) {
            try {
                CompletableFuture.runAsync(clientStuck::check).get(5, TimeUnit.SECONDS);
            } catch (TimeoutException e) {
                logger.log(Level.WARNING, "Client stuck interrupted", e);
                System.exit(1);
            } catch (Exception e) {
                logger.log(Level.WARNING, e.getMessage());
            }
        }
    }
}
