syntax = "proto3";

package signaler;

service SignalerService {
    rpc CreateAuthToken(CreateAuthTokenRequest) returns (AuthToken);
    rpc ListCameras(ListCamerasRequest) returns (ListCamerasResponse);

    // CreateSession creates a new session that can be seen bv the provided Camera and Peer.
    //
    // Optionally, wait_for_update can be set to prevent returning until the Camera has seen the
    // session request, populated candidates, and returned a session offer.
    rpc CreateSession(CreateSessionRequest) returns (Session);
    // PopSession deletes a session from the list of sessions, and returns it.
    //
    // If there are no sessions, this blocks until one becomes available.
    rpc PopSession(PopSessionRequest) returns (Session);

    // CreateIceMessage adds the provided message to the list of candidates.
    rpc CreateIceMessage(CreateIceMessageRequest) returns (IceMessage);
    // PopIceCandidate delete a message from the list of messages and returns it.
    //
    // If there are no messages, this blocks until one becomes available.
    rpc PopIceMessage(PopIceMessageRequest) returns (IceMessage);

    // CreateSample creates a sample for the given camera.
    // If called without an auth token indicating a camera, an error
    // is returned.
    // TODO: this should be moved to a seperate service
    rpc CreateSample(CreateSampleRequest) returns (Sample);
    rpc ListSamples(ListSamplesRequest) returns (ListSamplesResponse);
}

message CreateAuthTokenRequest{
    // Homes this auth token should be registered too.
    string home = 1;

    message Camera {
        // Used to uniquely identifier this camera so clients can open
        // sessions with it.
        string id = 1;
    }
    message Client {}

    oneof type {
        Camera camera = 2;
        Client client = 3;
    }
}

message ListCamerasRequest {}

message ListCamerasResponse {
    repeated Camera cameras = 1;
}

message CreateSessionRequest {
    Session session = 1;

    // If true, will keep the connection alive until an update is received.
    // This is useful if we need to wait for a remote to detect the session
    // request and update it with their candidates, offer, or answer.
    bool wait_for_update = 2;
}

message PopSessionRequest {
    optional Session session = 1;
}

message UpdateSessionRequest {
    Session session = 1;

    // If true, will keep the connection alive until an update is received.
    // This is useful if we need to wait for a remote to detect the session
    // request and update it with their candidates, offer, or answer.
    bool wait_for_update = 2;
}

message ListSessionsRequest {}

message ListSessionsResponse {
    repeated Session sessions = 1;
}

message CreateIceMessageRequest {
    Session.Identifier session_identifier = 1;
    IceMessage ice_message = 2;
}

message PopIceMessageRequest {
    Session.Identifier session_identifier = 1;
}

message CreateSampleRequest{
    Sample sample = 1;
}

message ListSamplesRequest {
}

message ListSamplesResponse {
    repeated Sample samples = 1;
}

message Camera {
    message Identifier {
        string id = 1;
    }
    Identifier identifier = 1;
}

message IceMessage {
    oneof type {
        IceCandidate candidate = 1;
        IceSessionDescription session = 2;
        NoMoreCandidates no_more_candidates = 3;
    }
}

message NoMoreCandidates {}

message IceCandidate {
    // Copied from https://pkg.go.dev/github.com/pion/webrtc/v4#ICECandidateInit
    string candidate = 1;
    optional string sdp_mid = 2;
    optional int32 sdp_line_index = 3;
    optional string username_fragment = 4;
}

message IceSessionDescription {
    // Copied from https://pkg.go.dev/github.com/pion/webrtc/v4#SessionDescription
    int64 sdp_type = 1;
    string sdp = 2;
}

message Session {
    message Identifier {
        string id = 1;
    }
    Identifier id = 1;
    Camera.Identifier camera = 2;
}

message AuthToken {
    string token = 1;
}

message Sample{
    enum Type {
        UNSPECIFIED = 0;
        TEMPERATURE_C = 1;
        HUMIDITY = 2;
        PRESSURE = 3;
    }
    Type type = 1;
    double reading = 2;

    // Read-only; will be ignored in CreateSample.
    Camera.Identifier camera_id = 3;
}