syntax = "proto3";
package rockpaperscissors;
option go_package = "proto";

// https://cloud.google.com/service-management/reference/rpc/google.api#http
import "google/api/annotations.proto";
import "google/protobuf/field_mask.proto";

import "code.justin.tv/dta/rockpaperscissors/proto/project_metadata.proto";

// TODO: should we include fields for query filtering?
message ListProjectsRequest {
  // If true, also return any "archived" projects.
  bool include_archived = 1;
}

message ListProjectsResponse {
  // Only the project_id and project_name fields will be populated in the ProjectMetadata.
  repeated ProjectMetadata projects = 1;
}

message GetMetadataRequest {
  string project_id = 1;
}

// TODO: should we include fields for pagination?
// TODO: should we return back a list of unmatched projects_ids?
message GetMetadataResponse {
  ProjectMetadata project = 1;
}

message UpdateMetadataRequest {
  ProjectMetadata project_metadata = 1;

  // If provided, this is the project to apply the update to, used for renames.
  string project_id = 2;

  // If provided, only update the given fields from the provided metadata.
  google.protobuf.FieldMask mask = 3;
}

message UpdateMetadataResponse {
}

message IngestBlueprintRequest {
  SourceFilePath source = 1;
}

message IngestBlueprintResponse {
}

message ListTeamsRequest {
  // If true, also return any "archived" projects.
  bool include_archived = 1;
}

message ListTeamsResponse {
  message TeamEntry {
    string team_name = 1;
    // Only the project_id and project_name will be populated in the ProjectMetadata.
    repeated ProjectMetadata projects = 2;
  }
  repeated TeamEntry teams = 1;
}

message GetTeamRequest {
  string team_name = 1;
}

message GetTeamResponse {
  string team_name = 1;
  // Only the project_id and project_name will be populated in the ProjectMetadata.
  repeated ProjectMetadata projects = 2;
}

message ListOrgsRequest {
  // If true, also return any "archived" projects.
  bool include_archived = 1;

  // If true, also include lists of projects under each team in response.
  bool include_projects = 2;
}

message ListOrgsResponse {
  message OrgEntry {
    string org_name = 1;

    message TeamEntry {
      string team_name = 1;
      // Only the project_id and project_name will be populated in the ProjectMetadata.
      repeated ProjectMetadata projects = 2;
    }
    repeated TeamEntry teams = 2;
  }
  repeated OrgEntry orgs = 1;
}

message GetOrgRequest {
  string org_name = 1;

  // If true, also include lists of projects under each team in response.
  bool include_projects = 2;
}

message GetOrgResponse {
  string org_name = 1;

  message TeamEntry {
    string team_name = 1;
    // Only the project_id and project_name will be populated in the ProjectMetadata.
    repeated ProjectMetadata projects = 2;
  }
  repeated TeamEntry teams = 2;
}

service ProjectMetadataService {
  // Returns a list of all projects registered with the system.
  rpc ListProjects(ListProjectsRequest) returns (ListProjectsResponse) {
    option (google.api.http) = {
      get: "/api/v1/projects"
    };
  }

  // Returns detailed information about one or more projects.
  rpc GetMetadata(GetMetadataRequest) returns (GetMetadataResponse) {
    option (google.api.http) = {
      get: "/api/v1/projects/{project_id}"
    };
  }

  // Updates metadata for a project.
  rpc UpdateMetadata(UpdateMetadataRequest) returns (UpdateMetadataResponse) {
    option (google.api.http) = {
      put: "/api/v1/projects/{project_id}"
      body: "*"

      // To satisfy REST semantics, requests with the mask set must be PATCH
      additional_bindings {
        patch: "/api/v1/projects/{project_id}"
        body: "*"
      }

      // This isn't valid REST semantics but is convenient.
      additional_bindings {
        post: "/api/v1/projects"
        body: "*"
      }
    };
  }

  // Reads a blueprint from some code source, evaluates it, and then updates
  // the project metadata.
  rpc IngestBlueprint(IngestBlueprintRequest) returns (IngestBlueprintResponse) {}

  // Get a list of development teams.
  // This is based on what team each project declares itself to be a part of.
  rpc ListTeams(ListTeamsRequest) returns (ListTeamsResponse) {
    option (google.api.http) = {
      get: "/api/v1/teams"
    };
  }

  // Get details about a development team.
  // This is based on what team each project declares itself to be a part of.
  rpc GetTeam(GetTeamRequest) returns (GetTeamResponse) {
    option (google.api.http) = {
      get: "/api/v1/teams/{team_name}"
    };
  }

  // Get a list of team organizations.
  // This is based on what org each project declares itself to be a part of.
  rpc ListOrgs(ListOrgsRequest) returns (ListOrgsResponse) {
    option (google.api.http) = {
      get: "/api/v1/orgs"
    };
  }

  // Get details about an organization.
  // This is based on what org each project declares itself to be a part of.
  rpc GetOrg(GetOrgRequest) returns (GetOrgResponse) {
    option (google.api.http) = {
      get: "/api/v1/orgs/{org_name}"
    };
  }
}
