// Copyright 2018 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";

import "google/api/annotations.proto";
import "google/api/client.proto";
import "google/api/field_behavior.proto";
import "google/api/resource.proto";
import "google/longrunning/operations.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/struct.proto";
import "google/protobuf/timestamp.proto";
import "google/rpc/status.proto";
import "google/protobuf/field_mask.proto";

package google.showcase.grpcrest.v1beta1;

option go_package = "github.com/googleapis/gapic-showcase-grpcrest/server/genproto";
option java_package = "com.google.showcase.grpcrest.v1beta1";
option java_multiple_files = true;

option (google.api.resource_definition) = {
  type: "showcase.googleapis.com/AnythingGoes"
  pattern: "*"
};

// This service is used showcase the four main types of rpcs - unary, server
// side streaming, client side streaming, and bidirectional streaming. This
// service also exposes methods that explicitly implement server delay, and
// paginated calls. Set the 'showcase-trailer' metadata key on any method
// to have the values echoed in the response trailers.
service Echo {
  // This service is meant to only run locally on the port 7469 (keypad digits
  // for "show").
  option (google.api.default_host) = "localhost:7469";
  option (google.api.oauth_scopes) =
      "https://www.googleapis.com/auth/cloud-platform";

  // This method simply echos the request. This method is showcases unary rpcs.
  rpc Echo(EchoRequest) returns (EchoResponse) {
    option (google.api.http) = {
      post: "/v1beta1/echo:echo"
      body: "*"
    };
    option (google.api.method_signature) = "content";
    option (google.api.method_signature) = "error";
    option (google.api.method_signature) = "content,severity";
    option (google.api.method_signature) = "name";
    option (google.api.method_signature) = "parent";
    option (google.api.method_signature) = "";
  }

  // This method split the given content into words and will pass each word back
  // through the stream. This method showcases server-side streaming rpcs.
  rpc Expand(ExpandRequest) returns (stream EchoResponse) {
    option (google.api.http) = {
      post: "/v1beta1/echo:expand"
      body: "error"
    };
    option (google.api.method_signature) = "content,error";
  }

  // This is similar to the Expand method but instead of returning a stream of
  // expanded words, this method returns a paged list of expanded words.
  rpc PagedExpand(PagedExpandRequest) returns (PagedExpandResponse) {
    option (google.api.http) = {
      post: "/v1beta1/echo:pagedExpand"
      body: "*"
    };
  }

  rpc SimplePagedExpand(PagedExpandRequest) returns (PagedExpandResponse) {
    option (google.api.http) = {
      post: "/v1beta1/echo:pagedExpand"
      body: "*"
    };
    option (google.api.method_signature) = "";
  }

  // This method will wait the requested amount of and then return.
  // This method showcases how a client handles a request timing out.
  rpc Wait(WaitRequest) returns (google.longrunning.Operation) {
    option (google.api.http) = {
      post: "/v1beta1/echo:wait"
      body: "*"
    };
    option (google.longrunning.operation_info) = {
      response_type: "WaitResponse"
      metadata_type: "WaitMetadata"
    };
    option (google.api.method_signature) = "end_time";
    option (google.api.method_signature) = "ttl";
  }

  // This method will block (wait) for the requested amount of time
  // and then return the response or error.
  // This method showcases how a client handles delays or retries.
  rpc Block(BlockRequest) returns (BlockResponse) {
    option (google.api.http) = {
      post: "/v1beta1/echo:block"
      body: "*"
    };
  };

  // This method primarily tests Java name collisions by using the Object
  // message.
  rpc CollideName(EchoRequest) returns (Object) {
    option (google.api.http) = {
      post: "/v1beta1/echo:foo"
      body: "*"
    };
  }

  rpc NestedBinding(EchoRequest) returns (Object) {
    option (google.api.http) = {
      post: "/v1beta1/{foo_bar.name=projects/*/foobars/*}/echo:foo"
      body: "*"
      additional_bindings {
        post: "/v1beta1/{foo_bar.name=cats/*/dogs/*}/echo:foo"
        body: "*"
      }
      additional_bindings {
        post: "/v1beta1/{foo_bar.name=turtles/*/parrots/*}/echo:foo"
        body: "*"
      }
    };
  }

  rpc Chat(stream EchoRequest) returns (stream EchoResponse) {
    option (google.api.http) = {
      post: "/v1beta1/chat:chat"
      body: "error"
    };
  }

  rpc NoBinding(EchoRequest) returns (EchoResponse);

  //The request message contains a field name that is a Java keyword(case),
  //the field is also a resource and used in http annotations
  rpc UpdateCase(UpdateCaseRequest) returns (Case) {
    option (google.api.http) = {
      patch: "/v2beta/{case.name=projects/*/cases/*}"
      body: "case"
      additional_bindings {
        patch: "/v2beta/{case.name=organizations/*/cases/*}"
        body: "case"
      }
    };
    option (google.api.method_signature) = "case,update_mask";
  }
}

// Generator should not fail when encounter a service without methods
service EchoEmpy {
  option (google.api.default_host) = "localhost:7469";
}

// A severity enum used to test enum capabilities in GAPIC surfaces
enum Severity {
  UNNECESSARY = 0;
  NECESSARY = 1;
  URGENT = 2;
  CRITICAL = 3;
}

message UpdateCaseRequest {
  Case case = 1 [(google.api.field_behavior) = REQUIRED];

  google.protobuf.FieldMask update_mask = 2;
}

message Case {
  option (google.api.resource) = {
    type: "cloudsupport.googleapis.com/Case"
    pattern: "organizations/{organization}/cases/{case}"
    pattern: "projects/{project}/cases/{case}"
  };

  // The resource name for the case.
  string name = 1;

  string display_name = 2;

  string description = 3;
}

message Foobar {
  option (google.api.resource) = {
    type: "showcase.googleapis.com/Foobar"
    pattern: "projects/{project}/foobars/{foobar}"
    pattern: "projects/{project}/chocolate/variants/{variant}/foobars/{foobar}"
    pattern: "foobars/{foobar}"
    pattern: "bar_foos/{bar_foo}/foobars/{foobar}"
    pattern: "*"
  };

  string name = 1;
  string info = 2;
}

// The request message used for the Echo, Collect and Chat methods.
// If content or opt are set in this message then the request will succeed.
// If status is set in this message
// then the status will be returned as an error.
message EchoRequest {
  string name = 5 [
    (google.api.resource_reference).type = "showcase.googleapis.com/Foobar",
    (google.api.field_behavior) = REQUIRED
  ];

  string parent = 6 [
    (google.api.resource_reference).child_type =
        "showcase.googleapis.com/AnythingGoes",
    (google.api.field_behavior) = REQUIRED
  ];

  oneof response {
    // The content to be echoed by the server.
    string content = 1;

    // The error to be thrown by the server.
    google.rpc.Status error = 2;
  }

  // The severity to be echoed by the server.
  Severity severity = 3;

  Foobar foo_bar = 4;
}

// The response message for the Echo methods.
message EchoResponse {
  // The content specified in the request.
  string content = 1;

  // The severity specified in the request.
  Severity severity = 2;

  // Value field to test special case in Value type serialization.
  google.protobuf.Value value_field = 3;
}

// Tests name collisions with java.lang.Object.
message Object {
  // The content specified in the request.
  string content = 1;
}

// The request message for the Expand method.
message ExpandRequest {
  // The content that will be split into words and returned on the stream.
  string content = 1;

  // The error that is thrown after all words are sent on the stream.
  google.rpc.Status error = 2;

  repeated string info = 3;
}

// The request for the PagedExpand method.
message PagedExpandRequest {
  // The string to expand.
  string content = 1 [(google.api.field_behavior) = REQUIRED];

  // The amount of words to returned in each page.
  int32 page_size = 2;

  // The position of the page to be returned.
  string page_token = 3;
}

// The response for the PagedExpand method.
message PagedExpandResponse {
  // The words that were expanded.
  repeated EchoResponse responses = 1;

  // The next page token.
  string next_page_token = 2;
}

// The request for Wait method.
message WaitRequest {
  oneof end {
    // The time that this operation will complete.
    google.protobuf.Timestamp end_time = 1;

    // The duration of this operation.
    google.protobuf.Duration ttl = 4;
  }

  oneof response {
    // The error that will be returned by the server. If this code is specified
    // to be the OK rpc code, an empty response will be returned.
    google.rpc.Status error = 2;

    // The response to be returned on operation completion.
    WaitResponse success = 3;
  }
}

// The result of the Wait operation.
message WaitResponse {
  // This content of the result.
  string content = 1;
}

// The metadata for Wait operation.
message WaitMetadata {
  // The time that this operation will complete.
  google.protobuf.Timestamp end_time = 1;
}

// The request for Block method.
message BlockRequest {
  // The amount of time to block before returning a response.
  google.protobuf.Duration response_delay = 1;

  oneof response {
    // The error that will be returned by the server. If this code is specified
    // to be the OK rpc code, an empty response will be returned.
    google.rpc.Status error = 2;

    // The response to be returned that will signify successful method call.
    BlockResponse success = 3;
  }
}

// The response for Block method.
message BlockResponse {
  // This content can contain anything, the server will not depend on a value
  // here.
  string content = 1;
}
