package com.zb.mom.ww.mxgateway.client;

import galaxy_repository.v1.GalaxyRepositoryOuterClass.DeployEvent;
import galaxy_repository.v1.GalaxyRepositoryOuterClass.WatchDeployEventsRequest;
import io.grpc.stub.ClientCallStreamObserver;
import io.grpc.stub.ClientResponseObserver;
import io.grpc.stub.StreamObserver;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;

/**
 * Cancellable handle returned by the async {@code watchDeployEvents} variant.
 * Mirrors {@link MxGatewayEventSubscription} but for the Galaxy Repository
 * deploy-event stream.
 */
public final class DeployEventSubscription implements AutoCloseable {
    private final AtomicReference<ClientCallStreamObserver<WatchDeployEventsRequest>> requestStream =
            new AtomicReference<>();
    private final AtomicBoolean cancelled = new AtomicBoolean();

    ClientResponseObserver<WatchDeployEventsRequest, DeployEvent> wrap(StreamObserver<DeployEvent> observer) {
        return new ClientResponseObserver<>() {
            @Override
            public void beforeStart(ClientCallStreamObserver<WatchDeployEventsRequest> stream) {
                requestStream.set(stream);
                if (cancelled.get()) {
                    stream.cancel("client cancelled deploy event stream", null);
                }
            }

            @Override
            public void onNext(DeployEvent value) {
                observer.onNext(value);
            }

            @Override
            public void onError(Throwable error) {
                observer.onError(error);
            }

            @Override
            public void onCompleted() {
                observer.onCompleted();
            }
        };
    }

    /**
     * Cancels the underlying gRPC call. Safe to invoke before the call has
     * started; cancellation is recorded and applied as soon as the stream
     * attaches.
     */
    public void cancel() {
        cancelled.set(true);
        ClientCallStreamObserver<WatchDeployEventsRequest> stream = requestStream.get();
        if (stream != null) {
            stream.cancel("client cancelled deploy event stream", null);
        }
    }

    @Override
    public void close() {
        cancel();
    }
}
