package client;

// Client/Client.java class represents the client that has to relay on the compute engine
// to perform tasks remotely.
// it needs the compute interface from compute package
import compute.Compute;

// it also needs those to access the registry,
// so it can get remote object reference of the server
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.Scanner;

public class Client {
    private Client() {
    }

    public static void main(String[] args) {

        // normally, the address of the server is passed here on the command line as an
        // argument
        // we get that address from args[0] if provided, else we use null for localhost
        String host = (args.length < 1) ? null : args[0];
        String name = "Compute";

        try (Scanner scanner = new Scanner(System.in);) {

            // get the registry from host(server)
            Registry registry = LocateRegistry.getRegistry(host);

            // look up the remote object by name in the registry
            // stub is the a reference to the remote object
            Compute stub = (Compute) registry.lookup(name);

            // interactive client to perform operations
            System.out.println("Connected to ComputeEngine. Type 'exit' to quit.");
            while (true) {

                // get user input for first number
                System.out.println("Enter first number: ");
                String input = scanner.next();
                if (input.equalsIgnoreCase("exit")) {
                    System.out.println("Exiting client.");
                    break;
                }
                int a = validateNumber(input);

                // get user input for second number
                System.out.println("Enter second number: ");
                input = scanner.next();
                if (input.equalsIgnoreCase("exit")) {
                    System.out.println("Exiting client.");
                    break;
                }
                int b = validateNumber(input);

                // get user input for operand
                System.out.println("Enter operand (+, -, *, /, %): ");
                input = scanner.next();
                if (input.equalsIgnoreCase("exit")) {
                    System.out.println("Exiting client.");
                    break;
                }
                String operand = validateOperand(input);

                // create operation task
                Operation op = new Operation(a, b, operand);
                // execute task remotely
                int result = stub.executeTask(op);
                System.out.println("Result: " + a + " " + operand + " " + b + " = " + result);
            }
        } catch (Exception e) {
            System.err.println("Client exception: " + e.getMessage());
        }
    }

    // simple validation methods. Because It is said
    // "Be conservative on what you do, be liberal on what you accept from others"
    // for int parsing
    private static int validateNumber(String a) {
        try {
            return Integer.parseInt(a);
        } catch (NumberFormatException e) {
            System.err.println("Invalid number format: " + a + ". Defaulting to 0.");
            return 0;
        }
    }

    // For operand validation
    private static String validateOperand(String op) {
        switch (op) {
            case "+":
            case "-":
            case "*":
            case "/":
            case "%":
                return op;
            default:
                System.err.println("Invalid operand: " + op + ". Defaulting to '+'.");
                return "+";
        }
    }
}
