package meerkat.bulletinboard;

import meerkat.comm.CommunicationException;
import meerkat.protobuf.BulletinBoardApi.*;

import com.google.common.util.concurrent.FutureCallback;

import java.util.List;

/**
 * Created by Arbel Deutsch Peled on 08-Mar-16.
 * This interface defines the behaviour of a bulletin board synchronizer
 * This is used to make sure that data in a specific instance of a bulletin board server is duplicated to a sufficient percentage of the other servers
 */
public interface BulletinBoardSynchronizer extends Runnable {

    public enum SyncStatus{
        SYNCHRONIZED,   // No more messages to upload
        PENDING,        // Synchronizer is querying for data to upload and uploading it as needed
        SERVER_ERROR,   // Synchronizer encountered an error while uploading, but will retry
        STOPPED         // Stopped/Not started by user
    }

    /**
     * Initializes the synchronizer with the required data to function properly
     * @param localClient is a client for the temporary local storage server which contains only data to be uploaded
     * @param remoteClient is a client for the remote servers into which the data needs to be uploaded
     */
    public void init(DeletableSubscriptionBulletinBoardClient localClient, AsyncBulletinBoardClient remoteClient);

    /**
     * Returns the current server synchronization status
     * @return the current synchronization status
     */
    public SyncStatus getSyncStatus();

    /**
     * Creates a subscription to sync status changes
     * @param callback is the handler for any status changes
     */
    public void subscribeToSyncStatus(FutureCallback<SyncStatus> callback);

    /**
     * Returns the messages which have not yet been synchronized
     * @return the list of messages remaining to be synchronized
     */
    public List<BulletinBoardMessage> getRemainingMessages() throws CommunicationException;

    /**
     * Asynchronously returns the messages which have not yet been synchronized
     * @param callback is the handler for the list of messages
     */
    public void getRemainingMessages(FutureCallback<List<BulletinBoardMessage>> callback);

    /**
     * Returns the current number of unsynchronized messages
     * @return the current synchronization status
     */
    public long getRemainingMessagesCount() throws CommunicationException;

    /**
     * Creates a subscription to changes in the number of unsynchronized messages
     * @param callback is the handler for any status changes
     */
    public void subscribeToRemainingMessagesCount(FutureCallback<Integer> callback);

    /**
     * Starts the synchronization
     */
    @Override
    public void run();

    /**
     * Lets the Synchronizer know that there is new data to be uploaded
     * This is used to reduce the latency between local data-writes and uploads to the remote servers
     */
    public void nudge();

    /**
     * Stops the synchronization
     */
    public void stop();

}
