package de.serosystems.grx.example;

import com.google.protobuf.Empty;
import de.serosystems.proto.v3.grx.receiverd.ReceiverDProto;
import de.serosystems.proto.v3.grx.receiverd.ReceiverdGrpc;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;

/**
 * Example: Query the radio front-end status from the GRX receiver.
 *
 * <p>This example connects to the Receiverd service and retrieves information about
 * each radio front-end, including its band, gain settings, noise level, and
 * antenna configuration.</p>
 *
 * <p>Usage: {@code java DeviceStatus [host]}</p>
 * <p>Default host: YOUR_GRX_IP</p>
 */
public class DeviceStatus {

	/** Default IP address of the GRX receiver. */
	private static final String DEFAULT_HOST = "YOUR_GRX_IP";

	/** Receiverd gRPC port. */
	private static final int RECEIVERD_PORT = 5303;

	public static void main(String[] args) {
		// Use the first CLI argument as hostname, or fall back to the default
		String host = args.length > 0 ? args[0] : DEFAULT_HOST;

		// Create a plaintext gRPC channel to the Receiverd service
		ManagedChannel channel = ManagedChannelBuilder.forAddress(host, RECEIVERD_PORT)
				.usePlaintext()
				.build();

		try {
			// Create a blocking (synchronous) stub for the Receiverd service
			ReceiverdGrpc.ReceiverdBlockingStub stub = ReceiverdGrpc.newBlockingStub(channel);

			// Call GetRadioFrontEndStatus to retrieve status of all radio front-ends
			ReceiverDProto.GetRadioFrontEndStatusReply status =
					stub.getRadioFrontEndStatus(Empty.getDefaultInstance());

			// --- Print radio front-end information ---
			System.out.printf("The receiver has %d radio front-end(s).%n",
					status.getRadioFrontEndStatusCount());

			for (ReceiverDProto.RadioFrontEndStatus rf : status.getRadioFrontEndStatusList()) {
				System.out.printf("%n\tRadio front-end %s-%d:%n",
						rf.getBand().name(), rf.getPerBandIndex());
				System.out.printf("\t\tNoise Level:          %.3f dBm%n", rf.getNoiseLevel());
				System.out.printf("\t\tExternal Fixed Gain:  %.3f dB%n", rf.getExternalFixedGain());
				System.out.printf("\t\tRX Chain Fixed Gain:  %.3f dB%n", rf.getRxChainFixedGain());
				System.out.printf("\t\tRX Chain Variable Gain: %.3f dB%n", rf.getRxChainVariableGain());
				System.out.printf("\t\tMin Observed Signal:  %.3f dBm%n", rf.getMinimumObservedSignalLevel());
				System.out.printf("\t\tEstimated Gain:       %.3f dB%n", rf.getEstimatedGain());
				System.out.printf("\t\tAntenna Port:         %s%n", rf.getAntennaId());

					// Print tunable state if this is a tunable channel
				if (rf.hasTunableState() && rf.getTunableState().getAvailable()) {
					ReceiverDProto.RadioFrontEndStatus.TunableState ts = rf.getTunableState();
					System.out.printf("\t\tTunable Center Freq:  %d Hz%n", ts.getCenterFrequency());
					System.out.printf("\t\tTunable Sample Rate:  %d Sps%n", ts.getSampleRate());
					System.out.printf("\t\tTunable Bandwidth:    %d Hz%n", ts.getBandwidth());
				}
			}

			// --- Print antenna port information ---
			System.out.printf("%nThe receiver has %d antenna port(s):%n",
					status.getAntennaStatusCount());

			status.getAntennaStatusMap().forEach((key, ant) -> {
				System.out.printf("\tAntenna port %s:%n", key);
				System.out.printf("\t\tLabel:              %s%n", ant.getLabel());
				System.out.printf("\t\tPower Supply:       %s%n",
						ant.getHasSupplyEnable()
								? (ant.getSupplyEnable() ? "enabled" : "disabled")
								: "N/A");
				System.out.printf("\t\tPower Supply Fault: %s%n", ant.getSupplyFault().name());
			});

			// --- Print antenna switch information ---
			System.out.printf("%nThe receiver has %d antenna switch(es):%n",
					status.getAntennaSwitchStatusCount());

			status.getAntennaSwitchStatusMap().forEach((key, sw) -> {
				System.out.printf("\tAntenna switch %s (%s):%n", sw.getId(), sw.getLabel());
				System.out.printf("\t\tState: '%s' (%s)%n",
						sw.getStateId(),
						sw.getStateIdToLabelMap().getOrDefault(sw.getStateId(), "unknown"));
			});

		} catch (Exception e) {
			System.err.println("Error communicating with receiver: " + e.getMessage());
			e.printStackTrace();
		} finally {
			// Always shut down the channel to release resources
			channel.shutdownNow();
		}
	}
}
