package meerkat.bulletinboard;

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

import static meerkat.protobuf.BulletinBoardApi.*;

import java.util.List;

/**
 * Created by talm on 24/10/15.
 */
public interface BulletinBoardClient {

    /**
     * Initialize the client to use some specified servers
     * @param clientParams contains the parameters required for the client setup
     */
    void init(BulletinBoardClientParams clientParams);

    /**
     * Post a message to the bulletin board in a synchronous 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
     * @return a unique message ID for the message, that can be later used to retrieve the batch
     * @throws CommunicationException
     */
    MessageID postMessage(BulletinBoardMessage msg) throws CommunicationException;

    /**
     * Check how "safe" a given message is in a synchronous manner
     * @param id is the unique message identifier for retrieval
     * @return a normalized "redundancy score" from 0 (local only) to 1 (fully published)
     * @throws CommunicationException
     */
    float getRedundancy(MessageID id) throws CommunicationException;

    /**
     * Read all messages posted matching the given filter in a synchronous 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)
     * @return the list of messages
     */
    List<BulletinBoardMessage> readMessages(MessageFilterList filterList) throws CommunicationException;

    /**
     * Breaks up a bulletin board message into chunks and posts it as a batch message
     * @param msg is the message to post
     * @param chunkSize is the maximal chunk size in bytes
     * @return the unique message ID
     * @throws CommunicationException if operation is unsuccessful
     */
    MessageID postAsBatch(BulletinBoardMessage msg, int chunkSize) throws CommunicationException;

    /**
     * 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
     * @return the complete message
     * @throws CommunicationException if operation is unsuccessful
     */
    BulletinBoardMessage readMessage(MessageID msgID) throws CommunicationException;

    /**
     * Read batch data for a specific stub message
     * @param stub is a batch message stub
     * @return a new BulletinBoardMessage containing both metadata from the stub and actual data from the server
     * @throws CommunicationException if operation is unsuccessful
     * @throws IllegalArgumentException if the received message is not a stub
     */
    BulletinBoardMessage readBatchData(BulletinBoardMessage stub) throws CommunicationException, IllegalArgumentException;

    /**
     * Create a SyncQuery to test against that corresponds with the current server state for a specific filter list
     * Should only be called on instances for which the actual server contacted is known (i.e. there is only one server)
     * @param generateSyncQueryParams defines the required information needed to generate the query
     *                    These are represented as fractions of the total number of relevant messages
     * @return The generated SyncQuery
     * @throws CommunicationException when no DB can be contacted
     */
    SyncQuery generateSyncQuery(GenerateSyncQueryParams generateSyncQueryParams) throws CommunicationException;

    /**
     * Closes all connections, if any.
     * This is done in a synchronous (blocking) way.
     */
    void close();

}
