package com.atlassian.bitbucket.mesh.request;

import io.grpc.Metadata;
import io.grpc.ServerCall;
import io.grpc.ServerCallHandler;
import io.grpc.ServerInterceptor;

/**
 * Extracts request metadata from the {@link ServerCall} and headers when a new call is received and creates the
 * {@link RequestContext}, which makes request details available for processing as well as inclusion in the logs.
 * {@link RequestManager#withContext} also handles writing the access log entry for the request.
 */
public class RequestServerInterceptor implements ServerInterceptor {

    private final RequestManager requestManager;

    public RequestServerInterceptor(RequestManager requestManager) {
        this.requestManager = requestManager;
    }

    @Override
    public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> call, Metadata headers,
                                                                 ServerCallHandler<ReqT, RespT> next) {
        GrpcRequestDescriptor descriptor = new GrpcRequestDescriptor(call, headers);

        return requestManager.withContext(descriptor,
                ctx -> new RequestServerCallListener<>(
                        next.startCall(new RequestServerCall<>(call, descriptor), headers),
                        descriptor));
    }
}
