package meerkat.bulletinboard.workers.multiserver;

import com.google.common.util.concurrent.FutureCallback;
import com.google.protobuf.Timestamp;
import meerkat.bulletinboard.AsyncBulletinBoardClient.BatchIdentifier;
import meerkat.bulletinboard.BatchDataContainer;
import meerkat.bulletinboard.MultiServerBatchIdentifier;
import meerkat.bulletinboard.MultiServerWorker;
import meerkat.bulletinboard.SingleServerBulletinBoardClient;
import meerkat.crypto.DigitalSignature;
import meerkat.protobuf.Crypto;
import meerkat.protobuf.Crypto.Signature;

import java.util.Iterator;
import java.util.List;

/**
 * Created by Arbel Deutsch Peled on 27-Dec-15.
 */
public class MultiServerCloseBatchWorker extends MultiServerWorker<MultiServerBatchIdentifier, Boolean> {

    private final Timestamp timestamp;
    private final Iterable<Crypto.Signature> signatures;

    public MultiServerCloseBatchWorker(List<SingleServerBulletinBoardClient> clients,
                                       int minServers, MultiServerBatchIdentifier payload, Timestamp timestamp, Iterable<Crypto.Signature> signatures,
                                       int maxRetry, FutureCallback<Boolean> futureCallback) {

        super(clients, minServers, payload, maxRetry, futureCallback);

        this.timestamp = timestamp;
        this.signatures = signatures;

    }

    @Override
    public void run() {

        Iterator<BatchIdentifier> identifierIterator = payload.getIdentifiers().iterator();

        // Iterate through client

        for (SingleServerBulletinBoardClient client : clients) {

            if (identifierIterator.hasNext()) {

                // Fetch the batch identifier supplied by the specific client (may be null if batch open failed on client

                BatchIdentifier identifier = identifierIterator.next();

                if (identifier != null) {

                    // Post the data with the matching identifier to the client
                    client.closeBatch(identifier, timestamp, signatures, this);

                } else {

                    // Count servers with no batch identifier as failed
                    maxFailedServers.decrementAndGet();

                }

            }

        }

    }

    @Override
    public void onSuccess(Boolean result) {
        if (minServers.decrementAndGet() <= 0){
            succeed(result);
        }
    }

    @Override
    public void onFailure(Throwable t) {
        if (maxFailedServers.decrementAndGet() <= 0){
            fail(t);
        }
    }


}
