package meerkat.bulletinboard;

import com.google.protobuf.BoolValue;
import com.google.protobuf.Int32Value;
import com.google.protobuf.Int64Value;
import meerkat.comm.CommunicationException;
import meerkat.comm.MessageOutputStream;
import meerkat.protobuf.BulletinBoardApi.*;


/**
 * Created by Arbel on 07/11/15.
 * 
 * This interface refers to a single instance of a Bulletin Board
 * An implementation of this interface may use any DB and be hosted on any machine.
 */

public interface BulletinBoardServer {
	
	/**
	 * This method initializes the server by reading the signature data and storing it
	 * It also establishes the connection to the DB
	 * @throws CommunicationException on DB connection error
	 */
	public void init() throws CommunicationException;

	/**
     * Post a message to bulletin board.
     * @param msg is the actual (signed) message
	 * @return TRUE if the message has been authenticated and FALSE otherwise (in ProtoBuf form)
	 * @throws CommunicationException on DB connection error
     */
	public BoolValue postMessage(BulletinBoardMessage msg) throws CommunicationException;

	 /**
	  * Read all posted messages matching the given filters
	  * @param filterList return only messages that match the filters (empty list or null means no filtering)
	  * @param out is an output stream into which the matching messages are written
	  * @throws CommunicationException on DB connection error
	  */
	public void readMessages(MessageFilterList filterList, MessageOutputStream<BulletinBoardMessage> out) throws CommunicationException;

	/**
	 * Return the number of posted messages matching the given filters
	 * @param filterList count only messages that match the filters (empty list or null means no filtering)
	 * @return an IntMsg containing the number of messages that match the filter
	 * @throws CommunicationException on DB connection error
	 */
	public Int32Value getMessageCount(MessageFilterList filterList) throws CommunicationException;

	/**
	 * Informs server about a new batch message
	 * @param message contains the required data about the new batch
	 * @return a unique batch identifier for the new batch ; -1 if batch creation was unsuccessful
	 * @throws CommunicationException on DB connection error
     */
	public Int64Value beginBatch(BeginBatchMessage message) throws CommunicationException;

	/**
	 * Posts a chunk of a batch message to the bulletin board
	 * Note that the existence and contents of a batch message are not available for reading before the batch is finalized
	 * @param batchMessage contains the (partial) data this message carries as well as meta-data required in order to place the data
	 *                     in the correct position inside the correct batch
	 * @return TRUE if the message is accepted and successfully saved and FALSE otherwise
	 * 		Specifically, if the batch is already closed: the value returned will be FALSE
	 * 		However, requiring to open a batch before insertion of messages is implementation-dependent
	 * @throws CommunicationException on DB connection error
	 */
	public BoolValue postBatchMessage(BatchMessage batchMessage) throws CommunicationException;

	/**
	 * Attempts to close and finalize a batch message
	 * @param message contains the data necessary to close the batch; in particular: the signature for the batch
	 * @return TRUE if the batch was successfully closed, FALSE otherwise
	 * 		Specifically, if the signature is invalid or if some of the batch parts have not yet been submitted: the value returned will be FALSE
	 * @throws CommunicationException on DB connection error
     */
	public BoolValue closeBatch(CloseBatchMessage message) throws CommunicationException;

	/**
	 * Reads a batch message from the server (starting with the supplied position)
	 * @param batchQuery specifies which batch and what parts of it to retrieve
	 * @param out is a stream of the ordered batch messages starting from the specified start position (if given) or from the beginning (if omitted)
	 * @throws CommunicationException on DB connection error
	 * @throws IllegalArgumentException if message ID does not specify a batch
     */
	public void readBatch(BatchQuery batchQuery, MessageOutputStream<BatchChunk> out) throws CommunicationException, IllegalArgumentException;

	/**
	 * Create a SyncQuery to test against that corresponds with the current server state for a specific filter list
	 * @param generateSyncQueryParams defines the information needed to generate the query
	 * @return The generated SyncQuery
	 * @throws CommunicationException on DB connection error
	 */
	public SyncQuery generateSyncQuery(GenerateSyncQueryParams generateSyncQueryParams) throws CommunicationException;

	/**
	 * Queries the database for sync status with respect to a given sync query
	 * @param syncQuery contains a succinct representation of states to compare to
	 * @return a SyncQueryResponse object containing the representation of the most recent state the database matches
	 * @throws CommunicationException
     */
	public SyncQueryResponse querySync(SyncQuery syncQuery) throws CommunicationException;

	 /**
	 * This method closes the connection to the DB
	 * @throws CommunicationException on DB connection error
	 */
	public void close() throws CommunicationException;
}
