package com.atlassian.bitbucket.mesh.git;

import com.atlassian.bitbucket.mesh.git.batch.BatchChange;
import com.atlassian.bitbucket.mesh.git.batch.BatchChangeCallback;
import com.atlassian.bitbucket.mesh.rpc.v1.RpcBatchChangesResponseFragment;
import io.grpc.stub.StreamObserver;

import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.List;

class ObserverBatchChangeCallback
        extends AbstractObserverCallback<RpcBatchChangesResponseFragment>
        implements BatchChangeCallback {

    private final List<BatchChange> batchChanges;

    ObserverBatchChangeCallback(StreamObserver<RpcBatchChangesResponseFragment> observer) {
        super(observer);

        batchChanges = new ArrayList<>(FRAGMENT_SIZE);
    }

    @Override
    public void onBatchChange(@Nonnull BatchChange batchChange) {
        batchChanges.add(batchChange);
        if (batchChanges.size() >= FRAGMENT_SIZE) {
            sendFragment();
        }
    }

    private void sendFragment() {
        RpcBatchChangesResponseFragment.Builder builder = RpcBatchChangesResponseFragment.newBuilder();
        batchChanges.forEach(batchChange -> builder.addBatchChanges(batchChange.toRpc()));
        batchChanges.clear();

        observer.onNext(builder.build());
    }

    void onEnd() {
        sendLastFragment();

        observer.onCompleted();
    }

    private void sendLastFragment() {
        if (!batchChanges.isEmpty()) {
            sendFragment();
        }
    }
}
