syntax = "proto3";
package foxtrot;
import "ft_types.proto";
import "ft_error.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/duration.proto";

enum capability_types
{
    VALUE_READONLY = 0;
    VALUE_READWRITE = 1;
    ACTION = 2;
    STREAM = 3;
    CONSTRUCTOR = 4;
}


message devcapability
{
    capability_types tp = 1;
    string capname = 2;
    uint32 capid = 8;

    repeated string argnames = 3;
    repeated variant_descriptor argtypes = 4;
    //TODO: allow for return of vector types
    oneof return
    {
      variant_descriptor rettp = 5;
      byte_data_types vecrettp = 6;
      bool dynamic_rettp = 7;
    }
}



message capability_argument
{
    uint32 position = 1;
    ft_variant value = 2;
}

message capability_request
{
    uint32 msgid = 1;
    uint32 devid = 2;
    string capname = 3;
    uint32 capid = 6;
    repeated capability_argument args = 4; 
    uint32 contention_timeout = 5;
}

message capability_response
{
    uint32 msgid = 1;
    uint32 devid = 2;
    string capname = 3;
    uint32 capid = 7;
    ft_variant returnval = 4;
    errstatus err = 5;
    google.protobuf.Timestamp tstamp = 6;
    google.protobuf.Timestamp tstamp_dispatch = 8;
}

message chunk_request
{ 
    uint32 msgid = 1;
    uint32 devid = 2;
    string capname = 3;
    uint32 capid = 8;
    repeated capability_argument args = 4;
    uint32 chunksize = 6;
    uint32 contention_timeout = 7;

}

message datachunk
{
    bytes data = 1;
    uint32 msgid = 2;
    uint32 devid = 3;
    uint32 capid = 8;
    string capname = 4;
    errstatus err = 6;
    byte_data_types dtp = 7;

}


message bulkdata_chunk
{
  bytes data = 1;
  byte_data_types dtp = 2;
  errstatus err =3;
  string cpp_type_name = 4;
  uint32 pagenum = 5;
  uint32 totalnum = 6;
}

message bulkdata_request
{
  handlechooser handle = 1;
  uint32 chunksize = 2;
}


message devdescribe
{
    uint32 devid = 1;    
    string devtype = 2;
    string devcomment = 3;
    repeated devcapability caps = 4;
    
}

message servdescribe
{
    string servcomment = 1;
    string version = 4;
    map<uint32, devdescribe> devs_attached = 2;
    errstatus err = 3;
}

message devicechooser
{
  uint32 devid = 1;
}

message device_setup_request
{
  string devtypename = 1;
  string devcomment = 2;
  repeated capability_argument args = 3; 
}

message device_setup_response
{
  errstatus err = 1;
  devdescribe dev = 2;
}

message handlechooser
{
  uint64 handle = 1;
  string cpp_type_name = 2;
}

message handlelist
{
  repeated handlechooser handles = 1;

}


enum stream_control_commands
{
    stop = 0;
    start = 1;
}

message stream_control
{
  capability_request req = 1;
  stream_control_commands cmd = 2;
  google.protobuf.Duration interval = 3;
}

enum async_control_commands
{
  dispatch = 0;
  check = 1;
  get = 2;
  defer = 3;
  run_all = 4;
}

message async_control
{
  capability_request req = 1;
  async_control_commands cmd = 2;
}

message async_response
{
  bool done = 1;
  capability_response resp = 2;
}


service capability
{
  rpc InvokeCapability (capability_request) returns (capability_response);
  rpc DescribeServer(empty) returns (servdescribe);
  rpc FetchData(chunk_request) returns (stream datachunk);
  rpc CloseDevice(devicechooser) returns (errstatus);
  rpc RescanDevices(empty) returns (errstatus);
  rpc SetupDevice(device_setup_request) returns (device_setup_response);

  rpc ListHandles(empty) returns (handlelist);
  rpc DisposeHandle(handlechooser) returns (errstatus);

  rpc StreamCapability(stream stream_control) returns (stream capability_response);
  rpc BulkDataDownload(bulkdata_request) returns (stream bulkdata_chunk);
  rpc InvokeServerAsync(stream async_control) returns (stream async_response);
  
}

