syntax = "proto3";

package meerkat;

option java_package = "meerkat.protobuf";

import 'meerkat/crypto.proto';
import 'google/protobuf/timestamp.proto';

message BoolMsg {
    bool value = 1;
}

message IntMsg {
    int32 value = 1;
}

message MessageID {
	// The ID of a message for unique retrieval.
	// Note that it is assumed that this ID is a function of the message itself.
	bytes ID = 1;
}

message UnsignedBulletinBoardMessage {
    // Optional tags describing message; Used for message retrieval
    repeated string tag = 1;

    // Timestamp of the message (as defined by client)
    google.protobuf.Timestamp timestamp = 2;

    // The payload of the message
    oneof dataType{

        // A unique message identifier
        bytes msgId = 3;

        // The actual content of the message
        bytes data = 4;

    }


}

message BulletinBoardMessage {
	
	// Serial entry number of message in database
	int64 entryNum = 1;

	// Unsigned raw data of message
    UnsignedBulletinBoardMessage msg = 2;

    // Signature of message (and tags), excluding the entry number.
    repeated meerkat.Signature sig = 3;

}

message BulletinBoardMessageList {
	
	repeated BulletinBoardMessage message = 1;
	
}

enum FilterType {
    MSG_ID = 0;			// Match exact message ID
    EXACT_ENTRY = 1;	// Match exact entry number in database (chronological)
    MAX_ENTRY = 2;		// Find all entries in database up to specified entry number (chronological)
    MIN_ENTRY = 3;      // Find all entries in database starting from specified entry number (chronological)
    SIGNER_ID = 4;		// Find all entries in database that correspond to specific signature (signer)
    TAG = 5;			// Find all entries in database that have a specific tag
    AFTER_TIME = 6;     // Find all entries in database that occurred on or after a given timestamp
    BEFORE_TIME = 7;    // Find all entries in database that occurred on or before a given timestamp

    // NOTE: The MAX_MESSAGES filter must remain the last filter type
    //       This is because the condition it specifies in an SQL statement must come last in the statement
    //       Keeping it last here allows for easily sorting the filters and keeping the code general
    MAX_MESSAGES = 8;	// Return at most some specified number of messages
}

message MessageFilter {
	
	FilterType type = 1;
	
	oneof filter{
		bytes id = 2;
		int64 entry = 3;
		string tag = 4;
		int64 maxMessages = 5;
        google.protobuf.Timestamp timestamp = 6;
	}
}

message MessageFilterList {
	
	// Combination of filters.
	// To be implemented using intersection ("AND") operations.
	repeated MessageFilter filter = 1;
	
}

// This message is used to start a batch transfer to the Bulletin Board Server
message BeginBatchMessage {
    repeated string tag = 1;        // Tags for the batch message
}

// This message is used to finalize and sign a batch transfer to the Bulletin Board Server
message CloseBatchMessage {
    int64 batchId = 1;                          // Unique temporary identifier for the batch
    int32 batchLength = 2;                      // Number of messages in the batch
    google.protobuf.Timestamp timestamp = 3;    // Timestamp of the batch (as defined by client)
    repeated meerkat.Signature sig = 4;         // Signatures on the (ordered) batch messages
}

// Container for single chunk of abatch message
message BatchChunk {
    bytes data = 1;
}

// List of BatchChunk; Only used for testing
message BatchChunkList {
    repeated BatchChunk data = 1;
}

// These messages comprise a batch message
message BatchMessage {
    int64 batchId = 1;              // Unique temporary identifier for the batch
    int32 serialNum = 2;            // Location of the message in the batch: starting from 0
    BatchChunk data = 3;            // Actual data
}

// This message is used to define a single query to the server to ascertain whether or not the server is synched with the client
//  up till a specified timestamp
message SingleSyncQuery {

    google.protobuf.Timestamp timeOfSync = 1;
    int64 checksum = 2;

}

// This message defines a complete server sync query
message SyncQuery {

    MessageFilterList filterList = 1;

    repeated SingleSyncQuery query = 2;

}

// This message defines the required information for generation of a SyncQuery instance by the server
message GenerateSyncQueryParams {

    // Defines the set of messages required
    MessageFilterList filterList = 1;

    // Defines the locations in the list of messages to calculate single sync queries for
    // The values should be between 0.0 and 1.0 and define the location in fractions of the size of the message set
    repeated float breakpointList = 2;

}

// This message defines the server's response format to a sync query
message SyncQueryResponse {

    // Serial entry number of current last entry in database
    // Set to zero (0) in case no query checksums match
    int64 lastEntryNum = 1;

    // Largest value of timestamp for which the checksums match
    google.protobuf.Timestamp lastTimeOfSync = 2;

}

// This message defines a query for retrieval of batch data
message BatchQuery {

    // The unique message ID if the batch
    MessageID msgID = 1;

    // The first chunk to retrieve (0 is the first chunk)
    int32 startPosition = 2;

}