syntax = "proto3";

package memos.api.v1;

import "api/v1/common.proto";
import "api/v1/markdown_service.proto";
import "api/v1/memo_relation_service.proto";
import "api/v1/reaction_service.proto";
import "api/v1/resource_service.proto";
import "google/api/annotations.proto";
import "google/api/client.proto";
import "google/api/field_behavior.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/field_mask.proto";
import "google/protobuf/timestamp.proto";

option go_package = "gen/api/v1";

service MemoService {
  // CreateMemo creates a memo.
  rpc CreateMemo(CreateMemoRequest) returns (Memo) {
    option (google.api.http) = {
      post: "/api/v1/memos"
      body: "*"
    };
  }
  // ListMemos lists memos with pagination and filter.
  rpc ListMemos(ListMemosRequest) returns (ListMemosResponse) {
    option (google.api.http) = {get: "/api/v1/memos"};
  }
  // SearchMemos searches memos.
  rpc SearchMemos(SearchMemosRequest) returns (SearchMemosResponse) {
    option (google.api.http) = {get: "/api/v1/memos:search"};
  }
  // GetMemo gets a memo.
  rpc GetMemo(GetMemoRequest) returns (Memo) {
    option (google.api.http) = {get: "/api/v1/{name=memos/*}"};
    option (google.api.method_signature) = "name";
  }
  // UpdateMemo updates a memo.
  rpc UpdateMemo(UpdateMemoRequest) returns (Memo) {
    option (google.api.http) = {
      patch: "/api/v1/{memo.name=memos/*}"
      body: "memo"
    };
    option (google.api.method_signature) = "memo,update_mask";
  }
  // DeleteMemo deletes a memo.
  rpc DeleteMemo(DeleteMemoRequest) returns (google.protobuf.Empty) {
    option (google.api.http) = {delete: "/api/v1/{name=memos/*}"};
    option (google.api.method_signature) = "name";
  }
  // ExportMemos exports memos.
  rpc ExportMemos(ExportMemosRequest) returns (ExportMemosResponse) {
    option (google.api.http) = {
      post: "/api/v1/memos:export",
      body: "*"
    };
  }
  // SetMemoResources sets resources for a memo.
  rpc SetMemoResources(SetMemoResourcesRequest) returns (google.protobuf.Empty) {
    option (google.api.http) = {
      patch: "/api/v1/{name=memos/*}/resources"
      body: "*"
    };
    option (google.api.method_signature) = "name";
  }
  // ListMemoResources lists resources for a memo.
  rpc ListMemoResources(ListMemoResourcesRequest) returns (ListMemoResourcesResponse) {
    option (google.api.http) = {get: "/api/v1/{name=memos/*}/resources"};
    option (google.api.method_signature) = "name";
  }
  // SetMemoRelations sets relations for a memo.
  rpc SetMemoRelations(SetMemoRelationsRequest) returns (google.protobuf.Empty) {
    option (google.api.http) = {
      patch: "/api/v1/{name=memos/*}/relations"
      body: "*"
    };
    option (google.api.method_signature) = "name";
  }
  // ListMemoRelations lists relations for a memo.
  rpc ListMemoRelations(ListMemoRelationsRequest) returns (ListMemoRelationsResponse) {
    option (google.api.http) = {get: "/api/v1/{name=memos/*}/relations"};
    option (google.api.method_signature) = "name";
  }
  // CreateMemoComment creates a comment for a memo.
  rpc CreateMemoComment(CreateMemoCommentRequest) returns (Memo) {
    option (google.api.http) = {
      post: "/api/v1/{name=memos/*}/comments",
      body: "comment"
    };
    option (google.api.method_signature) = "name";
  }
  // ListMemoComments lists comments for a memo.
  rpc ListMemoComments(ListMemoCommentsRequest) returns (ListMemoCommentsResponse) {
    option (google.api.http) = {get: "/api/v1/{name=memos/*}/comments"};
    option (google.api.method_signature) = "name";
  }
  // GetUserMemosStats gets stats of memos for a user.
  rpc GetUserMemosStats(GetUserMemosStatsRequest) returns (GetUserMemosStatsResponse) {
    option (google.api.http) = {get: "/api/v1/memos/stats"};
    option (google.api.method_signature) = "username";
  }
  // ListMemoReactions lists reactions for a memo.
  rpc ListMemoReactions(ListMemoReactionsRequest) returns (ListMemoReactionsResponse) {
    option (google.api.http) = {get: "/api/v1/{name=memos/*}/reactions"};
    option (google.api.method_signature) = "name";
  }
  // UpsertMemoReaction upserts a reaction for a memo.
  rpc UpsertMemoReaction(UpsertMemoReactionRequest) returns (Reaction) {
    option (google.api.http) = {
      post: "/api/v1/{name=memos/*}/reactions",
      body: "*"
    };
    option (google.api.method_signature) = "name";
  }
  // DeleteMemoReaction deletes a reaction for a memo.
  rpc DeleteMemoReaction(DeleteMemoReactionRequest) returns (google.protobuf.Empty) {
    option (google.api.http) = {delete: "/api/v1/reactions/{reaction_id}"};
    option (google.api.method_signature) = "reaction_id";
  }
}

enum Visibility {
  VISIBILITY_UNSPECIFIED = 0;
  PRIVATE = 1;
  PROTECTED = 2;
  PUBLIC = 3;
}

message Memo {
  // The name of the memo.
  // Format: memos/{id}
  // id is the system generated id.
  string name = 1;

  // The user defined id of the memo.
  string uid = 2;

  RowStatus row_status = 3;

  // The name of the creator.
  // Format: users/{id}
  string creator = 4;

  google.protobuf.Timestamp create_time = 5;

  google.protobuf.Timestamp update_time = 6;

  google.protobuf.Timestamp display_time = 7;

  string content = 8;

  repeated Node nodes = 9 [(google.api.field_behavior) = OUTPUT_ONLY];

  Visibility visibility = 10;

  bool pinned = 11;

  optional int32 parent_id = 12 [(google.api.field_behavior) = OUTPUT_ONLY];

  repeated Resource resources = 13 [(google.api.field_behavior) = OUTPUT_ONLY];

  repeated MemoRelation relations = 14 [(google.api.field_behavior) = OUTPUT_ONLY];

  repeated Reaction reactions = 15 [(google.api.field_behavior) = OUTPUT_ONLY];
}

message CreateMemoRequest {
  string content = 1;

  Visibility visibility = 2;
}

message ListMemosRequest {
  // The maximum number of memos to return.
  int32 page_size = 1;

  // A page token, received from a previous `ListMemos` call.
  // Provide this to retrieve the subsequent page.
  string page_token = 2;

  // Filter is used to filter memos returned in the list.
  // Format: "creator == users/{uid} && visibilities == ['PUBLIC', 'PROTECTED']"
  string filter = 3;
}

message ListMemosResponse {
  repeated Memo memos = 1;

  // A token, which can be sent as `page_token` to retrieve the next page.
  // If this field is omitted, there are no subsequent pages.
  string next_page_token = 2;
}

message SearchMemosRequest {
  // Filter is used to filter memos returned.
  // Format: "creator == users/{uid} && visibilities == ['PUBLIC', 'PROTECTED']"
  string filter = 1;
}

message SearchMemosResponse {
  repeated Memo memos = 1;
}

message GetMemoRequest {
  // The name of the memo.
  // Format: memos/{id}
  string name = 1;
}

message UpdateMemoRequest {
  Memo memo = 1;

  google.protobuf.FieldMask update_mask = 2;
}

message DeleteMemoRequest {
  // The name of the memo.
  // Format: memos/{id}
  string name = 1;
}

message ExportMemosRequest {
  // Same as ListMemosRequest.filter
  string filter = 1;
}

message ExportMemosResponse {
  bytes content = 1;
}

message SetMemoResourcesRequest {
  // The name of the memo.
  // Format: memos/{id}
  string name = 1;

  repeated Resource resources = 2;
}

message ListMemoResourcesRequest {
  // The name of the memo.
  // Format: memos/{id}
  string name = 1;
}

message ListMemoResourcesResponse {
  repeated Resource resources = 1;
}

message SetMemoRelationsRequest {
  // The name of the memo.
  // Format: memos/{id}
  string name = 1;

  repeated MemoRelation relations = 2;
}

message ListMemoRelationsRequest {
  // The name of the memo.
  // Format: memos/{id}
  string name = 1;
}

message ListMemoRelationsResponse {
  repeated MemoRelation relations = 1;
}

message CreateMemoCommentRequest {
  // The name of the memo.
  // Format: memos/{id}
  string name = 1;

  CreateMemoRequest comment = 2;
}

message ListMemoCommentsRequest {
  // The name of the memo.
  // Format: memos/{id}
  string name = 1;
}

message ListMemoCommentsResponse {
  repeated Memo memos = 1;
}

message GetUserMemosStatsRequest {
  // name is the name of the user to get stats for.
  // Format: users/{id}
  string name = 1;

  // timezone location
  // Format: uses tz identifier
  // https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
  string timezone = 2;

  // Same as ListMemosRequest.filter
  string filter = 3;
}

message GetUserMemosStatsResponse {
  // stats is the stats of memo creating/updating activities.
  // key is the year-month-day string. e.g. "2020-01-01".
  map<string, int32> stats = 1;
}

message ListMemoReactionsRequest {
  // The name of the memo.
  // Format: memos/{id}
  string name = 1;
}

message ListMemoReactionsResponse {
  repeated Reaction reactions = 1;
}

message UpsertMemoReactionRequest {
  // The name of the memo.
  // Format: memos/{id}
  string name = 1;

  Reaction reaction = 2;
}

message DeleteMemoReactionRequest {
  int32 reaction_id = 1;
}
