package de.serosystems.grx.example;

import de.serosystems.proto.v3.grx.CommonProto;
import de.serosystems.proto.v3.grx.samplestreamingd.SamplestreamingDProto;
import de.serosystems.proto.v3.grx.samplestreamingd.SamplestreamingdGrpc;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;

import java.util.Iterator;

/**
 * Example: Use the Samplestreamingd service to query stream properties and receive
 * raw sample blocks from a radio channel.
 *
 * <p>This example connects to the Samplestreamingd service, retrieves the stream
 * properties (center frequency, sample rate, calibration value) for the 1090 MHz
 * channel, then requests a fixed number of sample blocks and prints metadata for
 * each block.</p>
 *
 * <p>Usage: {@code java SampleStreaming [host]}</p>
 * <p>Default host: YOUR_GRX_IP</p>
 */
public class SampleStreaming {

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

	/** Samplestreamingd gRPC port. */
	private static final int SAMPLESTREAMINGD_PORT = 5308;

	/** Number of sample blocks to receive. */
	private static final int BLOCK_COUNT = 5;

	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 Samplestreamingd service
		ManagedChannel channel = ManagedChannelBuilder.forAddress(host, SAMPLESTREAMINGD_PORT)
				.usePlaintext()
				.build();

		try {
			// Create a blocking stub for the Samplestreamingd service
			SamplestreamingdGrpc.SamplestreamingdBlockingStub stub =
					SamplestreamingdGrpc.newBlockingStub(channel);

			// Identify the radio channel we want to stream from (1090 MHz, index 0)
			CommonProto.RadioIdentification radioId = CommonProto.RadioIdentification.newBuilder()
					.setBand(CommonProto.Band.BAND_1090_MHZ)
					.setPerBandIndex(0)
					.build();

			// Step 1: Query the stream properties for this channel
			SamplestreamingDProto.StreamProperties props = stub.getStreamProperties(
					SamplestreamingDProto.GetStreamPropertiesRequest.newBuilder()
							.setRadioIdentification(radioId)
							.build());

			System.out.printf("Stream Properties:%n");
			System.out.printf("  Center Frequency:  %d Hz (%.3f MHz)%n",
					props.getCenterFrequency(), props.getCenterFrequency() / 1e6);
			System.out.printf("  Sample Rate:       %d Hz (%.3f MHz)%n",
					props.getSampleRate(), props.getSampleRate() / 1e6);
			System.out.printf("  Calibration Value: %.3f%n", props.getCalibrationValue());
			System.out.println();

			// Step 2: Request a fixed number of sample blocks
			SamplestreamingDProto.StartStreamRequest streamRequest =
					SamplestreamingDProto.StartStreamRequest.newBuilder()
							.setRadioIdentification(radioId)
							.setRequestedBlocks(BLOCK_COUNT)  // 0 = indefinite
							.build();

			// Open the blocking stream
			Iterator<SamplestreamingDProto.StartStreamReply> blockIterator =
					stub.startStream(streamRequest);

			System.out.printf("Receiving %d sample blocks...%n%n", BLOCK_COUNT);

			int blockNum = 0;
			while (blockIterator.hasNext()) {
				SamplestreamingDProto.StartStreamReply block = blockIterator.next();
				blockNum++;

				System.out.printf("Block %d:%n", blockNum);
				System.out.printf("  Timestamp:   %d%n", block.getBlockTimestamp());
				System.out.printf("  Data size:   %d bytes%n", block.getSamples().size());
				System.out.printf("  Lost blocks: %d%n", block.getLostBlocks());
				System.out.println();
			}

			System.out.printf("Done. Received %d blocks.%n", blockNum);

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