package meerkat.bulletinboard;

import com.google.common.util.concurrent.FutureCallback;
import com.google.protobuf.Timestamp;
import meerkat.protobuf.BulletinBoardApi.*;
import meerkat.protobuf.Crypto.Signature;

import java.util.List;

/**
 * Created by Arbel Deutsch Peled on 14-Dec-15.
 */
public interface AsyncBulletinBoardClient extends BulletinBoardClient {

    /**
     * Post a message to the bulletin board in an asynchronous manner
     * The message may be broken up by the client into a batch message, depending on implementation
     * @param msg is the message to be posted
     * @param callback is a class containing methods to handle the result of the operation
     * @return a unique message ID for the message, that can be later used to retrieve the batch
     */
    public MessageID postMessage(BulletinBoardMessage msg, FutureCallback<Boolean> callback);

    /**
     * Perform an end-to-end post of a message in batch form
     * @param completeBatch contains all the data of the batch
     * @param chunkSize is the maximum size of each chunk of the message in bytes
     * @param callback is a class containing methods to handle the result of the operation
     * @return a unique identifier for the batch message
     */
    public MessageID postAsBatch(BulletinBoardMessage completeBatch, int chunkSize, FutureCallback<Boolean> callback);

    /**
     * An interface for returning an opaque identifier for a batch message
     * This identifier is used to uniquely identify the batch until it is completely posted and signed
     * After the batch is fully posted: it is identified by its digest (like any message)
     * This can be implementation-specific (and not necessarily interchangeable between different implementations)
     */
    public interface BatchIdentifier {}

    /**
     * This message informs the server about the existence of a new batch message and supplies it with the tags associated with it
     * @param tags contains the tags used in the batch
     * @param callback is a callback function class for handling results of the operation
     *                 it receives a BatchIdentifier for use in subsequent batch post operations
     */
    public void beginBatch(Iterable<String> tags, FutureCallback<BatchIdentifier> callback);

    /**
     * This method posts batch data into an (assumed to be open) batch
     * It does not close the batch
     * @param batchIdentifier is the temporary batch identifier
     * @param batchChunkList is the (canonically ordered) list of data comprising the portion of the batch to be posted
     * @param startPosition is the location (in the batch) of the first entry in batchDataList
 *                      (optionally used to continue interrupted post operations)
 *                      The first position in the batch is position 0
     * @param callback is a callback function class for handling results of the operation
     * @throws IllegalArgumentException if the batch identifier given was of an illegal format
     */
    public void postBatchData(BatchIdentifier batchIdentifier, List<BatchChunk> batchChunkList,
                              int startPosition, FutureCallback<Boolean> callback) throws IllegalArgumentException;

    /**
     * Overloading of the postBatchData method which starts at the first position in the batch
     */
    public void postBatchData(BatchIdentifier batchIdentifier, List<BatchChunk> batchChunkList, FutureCallback<Boolean> callback)
            throws IllegalArgumentException;

    /**
     * Attempts to close a batch message
     * @param batchIdentifier is the temporary batch identifier
     * @param callback is a callback function class for handling results of the operation
     * @throws IllegalArgumentException if the batch identifier given was of an illegal format
     */
    public void closeBatch(BatchIdentifier batchIdentifier, Timestamp timestamp, Iterable<Signature> signatures, FutureCallback<Boolean> callback)
            throws IllegalArgumentException;

    /**
     * Check how "safe" a given message is in an asynchronous manner
     * The result of the computation is a rank between 0.0 and 1.0 indicating the fraction of servers containing the message
     * @param id is the unique message identifier for retrieval
     * @param callback is a callback function class for handling results of the operation
     */
    public void getRedundancy(MessageID id, FutureCallback<Float> callback);

    /**
     * Read all messages posted matching the given filter in an asynchronous manner
     * Note that if messages haven't been "fully posted", this might return a different
     * set of messages in different calls. However, messages that are fully posted
     * are guaranteed to be included
     * Also: batch messages are returned as stubs.
     * @param filterList return only messages that match the filters (null means no filtering)
     * @param callback is a callback function class for handling results of the operation
     */
    public void readMessages(MessageFilterList filterList, FutureCallback<List<BulletinBoardMessage>> callback);

    /**
     * Read a given message from the bulletin board
     * If the message is a batch: returns a complete message containing the batch data as well as the metadata
     * @param msgID is the ID of the message to be read
     * @param callback is a callback class for handling the result of the operation
     */
    public void readMessage(MessageID msgID, FutureCallback<BulletinBoardMessage> callback);

    /**
     * Read batch data for a specific stub message
     * @param stub is a batch message stub
     * @param callback is a callback class for handling the result of the operation
     * @return a new BulletinBoardMessage containing both metadata from the stub and actual data from the server
     * @throws IllegalArgumentException if the received message is not a stub
     */
    public void readBatchData(BulletinBoardMessage stub, FutureCallback<BulletinBoardMessage> callback) throws IllegalArgumentException;


    /**
     * Perform a Sync Query on the bulletin board
     * @param syncQuery defines the query
     * @param callback is a callback for handling the result of the query
     */
    public void querySync(SyncQuery syncQuery, FutureCallback<SyncQueryResponse> callback);

}
