syntax = "proto3";

package nominal.streaming_connection_service.v1;

import "buf/validate/validate.proto";
import "google/api/annotations.proto";
import "google/protobuf/timestamp.proto";
import "nominal/gen/v1/alias.proto";
import "nominal/gen/v1/error.proto";
import "nominal/streaming_connection_service/v1/opc_ua.proto";

option java_multiple_files = true;
option java_package = "io.nominal.streaming_connection_service.v1";

// Request to create a new streaming connection
message CreateStreamingConnectionRequest {
  string name = 1 [(buf.validate.field).required = true];

  optional string description = 2;

  StreamingConnectionDetails connection_details = 3 [(buf.validate.field).required = true];

  optional string workspace_rid = 4 [(nominal.gen.v1.alias) = {java_name: "io.nominal.api.rids.WorkspaceRid"}];
}

// Response for creating a new streaming connection
message CreateStreamingConnectionResponse {
  string streaming_connection_rid = 1 [(nominal.gen.v1.alias) = {java_name: "io.nominal.api.rids.StreamingConnectionRid"}];
}

// Error types for streaming connection operations
enum StreamingConnectionErrorType {
  STREAMING_CONNECTION_ERROR_TYPE_UNSPECIFIED = 0;
  STREAMING_CONNECTION_ERROR_TYPE_CONNECTION_NOT_FOUND = 1 [(nominal.gen.v1.error) = {
    code: "NOT_FOUND"
    message: " Streaming connection not found"
  }];
  STREAMING_CONNECTION_ERROR_TYPE_STREAMING_CONNECTION_ALREADY_RUNNING = 2 [(nominal.gen.v1.error) = {
    code: "ALREADY_EXISTS"
    message: "Streaming connection already running"
  }];
}

// Response for stream operations
message StopStreamResponse {
  bool success = 1;
}

message StartStreamResponse {
  bool success = 1;
}

// A configured streaming connection
message StreamingConnection {
  string streaming_connection_rid = 1 [(nominal.gen.v1.alias) = {java_name: "io.nominal.api.rids.StreamingConnectionRid"}];

  string name = 2;

  optional string description = 3;

  StreamingConnectionDetailsSecret connection_details = 4;

  StreamingConnectionStatus status = 6;

  google.protobuf.Timestamp created_at = 7;
}

// Union type for different streaming connection types
message StreamingConnectionDetails {
  oneof streaming_connection_details {
    option (buf.validate.oneof) = {required: true};

    OpcUaConnectionDetails opc_ua = 1;
  }
}

// Union type for different streaming connection secret types
message StreamingConnectionDetailsSecret {
  oneof streaming_connection_details {
    option (buf.validate.oneof) = {required: true};

    OpcUaConnectionDetailsSecret opc_ua = 1;
  }
}

// Union type for different streaming scraping types
message StreamingScrapingConfig {
  oneof streaming_scraping_config {
    option (buf.validate.oneof) = {required: true};

    OpcUaScrapingConfig opc_ua = 1;
  }
}

// The current status of a streaming connection
// buf:lint:ignore ENUM_VALUE_PREFIX
enum StreamingConnectionStatus {
  STREAMING_CONNECTION_STATUS_UNSPECIFIED = 0;
  CONNECTED = 1;
  DISCONNECTED = 2;
}

message GetStreamingConnectionRequest {
  string streaming_connection_rid = 1 [(nominal.gen.v1.alias) = {java_name: "io.nominal.api.rids.StreamingConnectionRid"}];
}

message GetStreamingConnectionResponse {
  StreamingConnection streaming_connection = 1;
}

message ListStreamingConnectionsRequest {
  repeated string workspace_rids = 1 [(nominal.gen.v1.alias) = {java_name: "io.nominal.api.rids.WorkspaceRid"}];
}

message ListStreamingConnectionsResponse {
  repeated StreamingConnection streaming_connections = 1;
}

message UpdateStreamingConnectionStatusRequest {
  string streaming_connection_rid = 1 [(nominal.gen.v1.alias) = {java_name: "io.nominal.api.rids.StreamingConnectionRid"}];
  StreamingConnectionStatus status = 2;
}

message UpdateStreamingConnectionStatusResponse {
  StreamingConnection streaming_connection = 1;
}

message StartStreamRequest {
  string streaming_connection_rid = 1 [(nominal.gen.v1.alias) = {java_name: "io.nominal.api.rids.StreamingConnectionRid"}];

  StreamingScrapingConfig scraping_config = 2;

  string target_dataset_rid = 3 [(nominal.gen.v1.alias) = {java_name: "io.nominal.api.rids.DatasetRid"}];
}

message StopStreamRequest {
  string streaming_connection_rid = 1 [(nominal.gen.v1.alias) = {java_name: "io.nominal.api.rids.StreamingConnectionRid"}];
}

// Service for managing streaming connections to external data sources.
// Supports OPC-UA with plans for MQTT, Kafka, and other protocols.
service StreamingConnectionService {
  // buf:lint:ignore RPC_REQUEST_STANDARD_NAME
  // Creates a new streaming connection configuration
  // buf:lint:ignore RPC_RESPONSE_STANDARD_NAME
  rpc CreateStreamingConnection(CreateStreamingConnectionRequest) returns (CreateStreamingConnectionResponse) {
    option (google.api.http) = {
      post: "/streaming-connection-service/v1/connections"
      body: "*"
    };
  }
  // Gets the details and status of a streaming connection
  rpc GetStreamingConnection(GetStreamingConnectionRequest) returns (GetStreamingConnectionResponse) {
    option (google.api.http) = {
      get: "/streaming-connection-service/v1/connections/{streaming_connection_rid}"
      response_body: "streaming_connection"
    };
  }

  // List all the streaming connections for a set of workspaces
  rpc ListStreamingConnections(ListStreamingConnectionsRequest) returns (ListStreamingConnectionsResponse) {
    option (google.api.http) = {get: "/streaming-connection-service/v1/connections"};
  }

  // Update the status of a streaming connection
  rpc UpdateStreamingConnectionStatus(UpdateStreamingConnectionStatusRequest) returns (UpdateStreamingConnectionStatusResponse) {
    option (google.api.http) = {
      post: "/streaming-connection-service/v1/connections/{streaming_connection_rid}/update-status"
      body: "*"
    };
  }

  // Starts streaming data for a connection
  rpc StartStream(StartStreamRequest) returns (StartStreamResponse) {
    option (google.api.http) = {
      post: "/streaming-connection-service/v1/connections/{streaming_connection_rid}/start"
      body: "*"
    };
  }
  // Stops streaming data for a connection
  rpc StopStream(StopStreamRequest) returns (StopStreamResponse) {
    option (google.api.http) = {
      post: "/streaming-connection-service/v1/connections/{streaming_connection_rid}/stop"
      body: "*"
    };
  }
}
