package meerkat.bulletinboard.workers.multiserver;

import com.google.common.util.concurrent.FutureCallback;
import meerkat.bulletinboard.MultiServerWorker;
import meerkat.bulletinboard.SingleServerBulletinBoardClient;
import meerkat.comm.CommunicationException;

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


/**
 * Created by Arbel Deutsch Peled on 27-Dec-15.
 */
public abstract class MultiServerGenericReadWorker<IN, OUT> extends MultiServerWorker<IN, OUT>{

    private Iterator<SingleServerBulletinBoardClient> clientIterator;

    private String errorString;

    public MultiServerGenericReadWorker(List<SingleServerBulletinBoardClient> clients,
                                        int minServers, IN payload, int maxRetry,
                                        FutureCallback<OUT> futureCallback) {

        super(clients, true, minServers, payload, maxRetry, futureCallback); // Shuffle clients on creation to balance load

        clientIterator = clients.iterator();
        errorString = "";

    }

    protected abstract void doRead(IN payload, SingleServerBulletinBoardClient client);

    /**
     * This method carries out the actual communication with the servers via HTTP Post
     * It accesses the servers in a random order until one answers it
     * Successful retrieval from any server terminates the method and returns the received values; The list is not changed
     */
    public void run(){

        // Iterate through servers

        if (clientIterator.hasNext()) {

            // Get next server
            SingleServerBulletinBoardClient client = clientIterator.next();

            // Retrieve answer from server
            doRead(payload, client);

        } else {
            fail(new CommunicationException("Could not contact any server. Errors follow:\n" + errorString));
        }

    }

    @Override
    public void onSuccess(OUT msg) {
        succeed(msg);
    }

    @Override
    public void onFailure(Throwable t) {
        //TODO: log
        errorString += t.getCause() + " " + t.getMessage() + "\n";
        run(); // Retry with next server
    }

}
