// Copyright 2023 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
//
//     http://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";

package google.maps.places.v1;

import "google/api/annotations.proto";
import "google/api/client.proto";
import "google/api/field_behavior.proto";
import "google/api/resource.proto";
import "google/geo/type/viewport.proto";
import "google/maps/places/v1/geometry.proto";
import "google/maps/places/v1/place.proto";

option cc_enable_arenas = true;
option csharp_namespace = "Google.Maps.Places.V1";
option go_package = "cloud.google.com/go/maps/places/apiv1/placespb;placespb";
option java_multiple_files = true;
option java_outer_classname = "PlacesServiceProto";
option java_package = "com.google.maps.places.v1";
option objc_class_prefix = "GMPSV1";
option php_namespace = "Google\\Maps\\Places\\V1";

// Service definition for the Places API.
// Note: every request actually requires a field mask set outside of
// the request proto (all/'*', is not assumed).  That can be set via either a
// side channel (SystemParameterContext) over RPC, or a header
// (X-Goog-FieldMask) over HTTP. See:
// https://cloud.google.com/apis/docs/system-parameters
service Places {
  option (google.api.default_host) = "places.googleapis.com";

  // Search for places near locations.
  rpc SearchNearby(SearchNearbyRequest) returns (SearchNearbyResponse) {
    option (google.api.http) = {
      post: "/v1/places:searchNearby"
      body: "*"
    };
  }

  // Text query based place search.
  rpc SearchText(SearchTextRequest) returns (SearchTextResponse) {
    option (google.api.http) = {
      post: "/v1/places:searchText"
      body: "*"
    };
  }

  // Get a photo media with a photo reference string.
  rpc GetPhotoMedia(GetPhotoMediaRequest) returns (PhotoMedia) {
    option (google.api.http) = {
      get: "/v1/{name=places/*/photos/*/media}"
    };
    option (google.api.method_signature) = "name";
  }

  // Get place details with a place id (in a name) string.
  rpc GetPlace(GetPlaceRequest) returns (Place) {
    option (google.api.http) = {
      get: "/v1/{name=places/*}"
    };
    option (google.api.method_signature) = "name";
  }
}

// Request proto for Search Nearby.
//
//
message SearchNearbyRequest {
  // The region to search.
  message LocationRestriction {
    oneof type {
      // A circle defined by center point and radius.
      Circle circle = 2;
    }
  }

  // How results will be ranked in the response.
  enum RankPreference {
    // RankPreference value not set. Will use rank by POPULARITY by default.
    RANK_PREFERENCE_UNSPECIFIED = 0;

    // Ranks results by distance.
    DISTANCE = 1;

    // Ranks results by popularity.
    POPULARITY = 2;
  }

  // Place details will be displayed with the preferred language if available.
  // If the language code is unspecified or unrecognized, place details of any
  // language may be returned, with a preference for English if such details
  // exist.
  //
  // Current list of supported languages:
  // https://developers.google.com/maps/faq#languagesupport.
  string language_code = 1;

  // The Unicode country/region code (CLDR) of the location where the
  // request is coming from. This parameter is used to display the place
  // details, like region-specific place name, if available. The parameter can
  // affect results based on applicable law.
  //
  // For more information, see
  // https://www.unicode.org/cldr/charts/latest/supplemental/territory_language_information.html.
  //
  //
  // Note that 3-digit region codes are not currently supported.
  string region_code = 2;

  // Included Place type (eg, "restaurant" or "gas_station") from
  // https://developers.google.com/maps/documentation/places/web-service/place-types.
  //
  // Up to 50 types from [Table
  // A](https://developers.google.com/maps/documentation/places/web-service/place-types#table-a)
  // may be specified.
  //
  // If there are any conflicting types, i.e. a type appears in both
  // included_types and excluded_types, an INVALID_ARGUMENT error is
  // returned.
  //
  // If a Place type is specified with multiple type restrictions, only places
  // that satisfy all of the restrictions are returned. For example, if we
  // have {included_types = ["restaurant"], excluded_primary_types =
  // ["restaurant"]}, the returned places provide "restaurant"
  // related services but do not operate primarily as "restaurants".
  repeated string included_types = 3;

  // Excluded Place type (eg, "restaurant" or "gas_station") from
  // https://developers.google.com/maps/documentation/places/web-service/place-types.
  //
  // Up to 50 types from [Table
  // A](https://developers.google.com/maps/documentation/places/web-service/place-types#table-a)
  // may be specified.
  //
  // If the client provides both included_types (e.g. restaurant) and
  // excluded_types (e.g. cafe), then the response should include places that
  // are restaurant but not cafe. The response includes places that match at
  // least one of the included_types and none of the excluded_types.
  //
  // If there are any conflicting types, i.e. a type appears in both
  // included_types and excluded_types, an INVALID_ARGUMENT error is returned.
  //
  // If a Place type is specified with multiple type restrictions, only places
  // that satisfy all of the restrictions are returned. For example, if we
  // have {included_types = ["restaurant"], excluded_primary_types =
  // ["restaurant"]}, the returned places provide "restaurant"
  // related services but do not operate primarily as "restaurants".
  repeated string excluded_types = 4;

  // Included primary Place type (e.g. "restaurant" or "gas_station") from
  // https://developers.google.com/maps/documentation/places/web-service/place-types.
  // A place can only have a single primary type from the supported types table
  // associated with it.
  //
  // Up to 50 types from [Table
  // A](https://developers.google.com/maps/documentation/places/web-service/place-types#table-a)
  // may be specified.
  //
  // If there are any conflicting primary types, i.e. a type appears in both
  // included_primary_types and excluded_primary_types, an INVALID_ARGUMENT
  // error is returned.
  //
  // If a Place type is specified with multiple type restrictions, only places
  // that satisfy all of the restrictions are returned. For example, if we
  // have {included_types = ["restaurant"], excluded_primary_types =
  // ["restaurant"]}, the returned places provide "restaurant"
  // related services but do not operate primarily as "restaurants".
  repeated string included_primary_types = 5;

  // Excluded primary Place type (e.g. "restaurant" or "gas_station") from
  // https://developers.google.com/maps/documentation/places/web-service/place-types.
  //
  // Up to 50 types from [Table
  // A](https://developers.google.com/maps/documentation/places/web-service/place-types#table-a)
  // may be specified.
  //
  // If there are any conflicting primary types, i.e. a type appears in both
  // included_primary_types and excluded_primary_types, an INVALID_ARGUMENT
  // error is returned.
  //
  // If a Place type is specified with multiple type restrictions, only places
  // that satisfy all of the restrictions are returned. For example, if we
  // have {included_types = ["restaurant"], excluded_primary_types =
  // ["restaurant"]}, the returned places provide "restaurant"
  // related services but do not operate primarily as "restaurants".
  repeated string excluded_primary_types = 6;

  // Maximum number of results to return. It must be between 1 and 20 (default),
  // inclusively. If the number is unset, it falls back to the upper limit. If
  // the number is set to negative or exceeds the upper limit, an
  // INVALID_ARGUMENT error is returned.
  int32 max_result_count = 7;

  // Required. The region to search.
  LocationRestriction location_restriction = 8
      [(google.api.field_behavior) = REQUIRED];

  // How results will be ranked in the response.
  RankPreference rank_preference = 9;
}

// Response proto for Search Nearby.
//
//
message SearchNearbyResponse {
  // A list of places that meets user's requirements like places
  // types, number of places and specific location restriction.
  repeated Place places = 1;
}

// Request proto for SearchText.
//
//
message SearchTextRequest {
  // How results will be ranked in the response.
  enum RankPreference {
    // RankPreference value not set. Will default to DISTANCE.
    RANK_PREFERENCE_UNSPECIFIED = 0;

    // Ranks results by distance.
    DISTANCE = 1;

    // Ranks results by relevance. Sort order determined by normal ranking
    // stack.
    RELEVANCE = 2;
  }

  // The region to search. This location serves as a bias which means results
  // around given location might be returned.
  message LocationBias {
    oneof type {
      // A rectangle box defined by northeast and southwest corner.
      // `rectangle.high()` must be the northeast point of the rectangle
      // viewport. `rectangle.low()` must be the southwest point of the
      // rectangle viewport. `rectangle.low().latitude()` cannot be greater than
      // `rectangle.high().latitude()`. This will result in an empty latitude
      // range. A rectangle viewport cannot be wider than 180 degrees.
      google.geo.type.Viewport rectangle = 1;

      // A circle defined by center point and radius.
      Circle circle = 2;
    }
  }

  // The region to search. This location serves as a restriction which means
  // results outside given location will not be returned.
  message LocationRestriction {
    oneof type {
      // A rectangle box defined by northeast and southwest corner.
      // `rectangle.high()` must be the northeast point of the rectangle
      // viewport. `rectangle.low()` must be the southwest point of the
      // rectangle viewport. `rectangle.low().latitude()` cannot be greater than
      // `rectangle.high().latitude()`. This will result in an empty latitude
      // range. A rectangle viewport cannot be wider than 180 degrees.
      google.geo.type.Viewport rectangle = 1;
    }
  }

  // Required. The text query for textual search.
  string text_query = 1 [(google.api.field_behavior) = REQUIRED];

  // Place details will be displayed with the preferred language if available.
  // If the language code is unspecified or unrecognized, place details of any
  // language may be returned, with a preference for English if such details
  // exist.
  //
  // Current list of supported languages:
  // https://developers.google.com/maps/faq#languagesupport.
  string language_code = 2;

  // The Unicode country/region code (CLDR) of the location where the
  // request is coming from. This parameter is used to display the place
  // details, like region-specific place name, if available. The parameter can
  // affect results based on applicable law.
  //
  // For more information, see
  // https://www.unicode.org/cldr/charts/latest/supplemental/territory_language_information.html.
  //
  //
  // Note that 3-digit region codes are not currently supported.
  string region_code = 3;

  // How results will be ranked in the response.
  RankPreference rank_preference = 4;

  // The requested place type. Full list of types supported:
  // https://developers.google.com/maps/documentation/places/web-service/place-types.
  // Only support one included type.
  string included_type = 6;

  // Used to restrict the search to places that are currently open.  The default
  // is false.
  bool open_now = 7;

  // Filter out results whose average user rating is strictly less than this
  // limit. A valid value must be a float between 0 and 5 (inclusively) at a
  // 0.5 cadence i.e. [0, 0.5, 1.0, ... , 5.0] inclusively. The input rating
  // will round up to the nearest 0.5(ceiling). For instance, a rating of 0.6
  // will eliminate all results with a less than 1.0 rating.
  double min_rating = 9;

  // Maximum number of results to return. It must be between 1 and 20,
  // inclusively. The default is 20.  If the number is unset, it falls back to
  // the upper limit. If the number is set to negative or exceeds the upper
  // limit, an INVALID_ARGUMENT error is returned.
  int32 max_result_count = 10;

  // Used to restrict the search to places that are marked as certain price
  // levels. Users can choose any combinations of price levels. Default to
  // select all price levels.
  repeated PriceLevel price_levels = 11;

  // Used to set strict type filtering for included_type. If set to true, only
  // results of the same type will be returned. Default to false.
  bool strict_type_filtering = 12;

  // The region to search. This location serves as a bias which means results
  // around given location might be returned. Cannot be set along with
  // location_restriction.
  LocationBias location_bias = 13;

  // The region to search. This location serves as a restriction which means
  // results outside given location will not be returned. Cannot be set along
  // with location_bias.
  LocationRestriction location_restriction = 14;
}

// Response proto for SearchText.
//
message SearchTextResponse {
  // A list of places that meet the user's text search criteria.
  repeated Place places = 1;
}

// Request for fetching a photo of a place using a photo resource name.
message GetPhotoMediaRequest {
  // Required. The resource name of a photo media in the format:
  // `places/{place_id}/photos/{photo_reference}/media`.
  //
  // The resource name of a photo as returned in a Place object's `photos.name`
  // field comes with the format
  // `places/{place_id}/photos/{photo_reference}`. You need to append `/media`
  // at the end of the photo resource to get the photo media resource name.
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "places.googleapis.com/PhotoMedia"
    }
  ];

  // Optional. Specifies the maximum desired width, in pixels, of the image. If
  // the image is smaller than the values specified, the original image will be
  // returned. If the image is larger in either dimension, it will be scaled to
  // match the smaller of the two dimensions, restricted to its original aspect
  // ratio. Both the max_height_px and max_width_px properties accept an integer
  // between 1 and 4800, inclusively. If the value is not within the allowed
  // range, an INVALID_ARGUMENT error will be returned.
  //
  // At least one of max_height_px or max_width_px needs to be specified. If
  // neither max_height_px nor max_width_px is specified, an INVALID_ARGUMENT
  // error will be returned.
  int32 max_width_px = 2 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Specifies the maximum desired height, in pixels, of the image. If
  // the image is smaller than the values specified, the original image will be
  // returned. If the image is larger in either dimension, it will be scaled to
  // match the smaller of the two dimensions, restricted to its original aspect
  // ratio. Both the max_height_px and max_width_px properties accept an integer
  // between 1 and 4800, inclusively. If the value is not within the allowed
  // range, an INVALID_ARGUMENT error will be returned.
  //
  // At least one of max_height_px or max_width_px needs to be specified. If
  // neither max_height_px nor max_width_px is specified, an INVALID_ARGUMENT
  // error will be returned.
  int32 max_height_px = 3 [(google.api.field_behavior) = OPTIONAL];

  // Optional. If set, skip the default HTTP redirect behavior and render a text
  // format (for example, in JSON format for HTTP use case) response. If not
  // set, an HTTP redirect will be issued to redirect the call to the image
  // media. This option is ignored for non-HTTP requests.
  bool skip_http_redirect = 4 [(google.api.field_behavior) = OPTIONAL];
}

// A photo media from Places API.
message PhotoMedia {
  option (google.api.resource) = {
    type: "places.googleapis.com/PhotoMedia"
    pattern: "places/{place_id}/photos/{photo_reference}/media"
    plural: "photoMedias"
    singular: "photoMedia"
  };

  // The resource name of a photo media in the format:
  // `places/{place_id}/photos/{photo_reference}/media`.
  string name = 1;

  // A short-lived uri that can be used to render the photo.
  string photo_uri = 2;
}

// Request for fetching a Place with a place id (in a name) string.
message GetPlaceRequest {
  // Required. A place ID returned in a Place (with "places/" prefix), or
  // equivalently the name in the same Place. Format:
  // `places/{place_id}`.
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = { type: "places.googleapis.com/Place" }
  ];

  // Optional. Place details will be displayed with the preferred language if
  // available.
  //
  // Current list of supported languages:
  // https://developers.google.com/maps/faq#languagesupport.
  string language_code = 2 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The Unicode country/region code (CLDR) of the location where the
  // request is coming from. This parameter is used to display the place
  // details, like region-specific place name, if available. The parameter can
  // affect results based on applicable law.
  // For more information, see
  // https://www.unicode.org/cldr/charts/latest/supplemental/territory_language_information.html.
  //
  //
  // Note that 3-digit region codes are not currently supported.
  string region_code = 3 [(google.api.field_behavior) = OPTIONAL];
}
