// Copyright 2024 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.

// Code generated by protoc-gen-go_gapic. DO NOT EDIT.

package publish

import (
	"bytes"
	"context"
	"fmt"
	"io"
	"math"
	"net/http"
	"net/url"
	"time"

	"cloud.google.com/go/longrunning"
	lroauto "cloud.google.com/go/longrunning/autogen"
	longrunningpb "cloud.google.com/go/longrunning/autogen/longrunningpb"
	publishpb "cloud.google.com/go/streetview/publish/apiv1/publishpb"
	gax "github.com/googleapis/gax-go/v2"
	"google.golang.org/api/googleapi"
	"google.golang.org/api/iterator"
	"google.golang.org/api/option"
	"google.golang.org/api/option/internaloption"
	gtransport "google.golang.org/api/transport/grpc"
	httptransport "google.golang.org/api/transport/http"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/protobuf/encoding/protojson"
	"google.golang.org/protobuf/proto"
	emptypb "google.golang.org/protobuf/types/known/emptypb"
)

var newStreetViewPublishClientHook clientHook

// StreetViewPublishCallOptions contains the retry settings for each method of StreetViewPublishClient.
type StreetViewPublishCallOptions struct {
	StartUpload              []gax.CallOption
	CreatePhoto              []gax.CallOption
	GetPhoto                 []gax.CallOption
	BatchGetPhotos           []gax.CallOption
	ListPhotos               []gax.CallOption
	UpdatePhoto              []gax.CallOption
	BatchUpdatePhotos        []gax.CallOption
	DeletePhoto              []gax.CallOption
	BatchDeletePhotos        []gax.CallOption
	StartPhotoSequenceUpload []gax.CallOption
	CreatePhotoSequence      []gax.CallOption
	GetPhotoSequence         []gax.CallOption
	ListPhotoSequences       []gax.CallOption
	DeletePhotoSequence      []gax.CallOption
}

func defaultStreetViewPublishGRPCClientOptions() []option.ClientOption {
	return []option.ClientOption{
		internaloption.WithDefaultEndpoint("streetviewpublish.googleapis.com:443"),
		internaloption.WithDefaultEndpointTemplate("streetviewpublish.UNIVERSE_DOMAIN:443"),
		internaloption.WithDefaultMTLSEndpoint("streetviewpublish.mtls.googleapis.com:443"),
		internaloption.WithDefaultUniverseDomain("googleapis.com"),
		internaloption.WithDefaultAudience("https://streetviewpublish.googleapis.com/"),
		internaloption.WithDefaultScopes(DefaultAuthScopes()...),
		internaloption.EnableJwtWithScope(),
		option.WithGRPCDialOption(grpc.WithDefaultCallOptions(
			grpc.MaxCallRecvMsgSize(math.MaxInt32))),
	}
}

func defaultStreetViewPublishCallOptions() *StreetViewPublishCallOptions {
	return &StreetViewPublishCallOptions{
		StartUpload: []gax.CallOption{
			gax.WithTimeout(60000 * time.Millisecond),
			gax.WithRetry(func() gax.Retryer {
				return gax.OnCodes([]codes.Code{}, gax.Backoff{
					Initial:    100 * time.Millisecond,
					Max:        60000 * time.Millisecond,
					Multiplier: 1.30,
				})
			}),
		},
		CreatePhoto: []gax.CallOption{
			gax.WithTimeout(60000 * time.Millisecond),
			gax.WithRetry(func() gax.Retryer {
				return gax.OnCodes([]codes.Code{}, gax.Backoff{
					Initial:    100 * time.Millisecond,
					Max:        60000 * time.Millisecond,
					Multiplier: 1.30,
				})
			}),
		},
		GetPhoto: []gax.CallOption{
			gax.WithTimeout(60000 * time.Millisecond),
			gax.WithRetry(func() gax.Retryer {
				return gax.OnCodes([]codes.Code{
					codes.Unavailable,
					codes.DeadlineExceeded,
				}, gax.Backoff{
					Initial:    100 * time.Millisecond,
					Max:        60000 * time.Millisecond,
					Multiplier: 1.30,
				})
			}),
		},
		BatchGetPhotos: []gax.CallOption{
			gax.WithTimeout(60000 * time.Millisecond),
			gax.WithRetry(func() gax.Retryer {
				return gax.OnCodes([]codes.Code{
					codes.Unavailable,
					codes.DeadlineExceeded,
				}, gax.Backoff{
					Initial:    100 * time.Millisecond,
					Max:        60000 * time.Millisecond,
					Multiplier: 1.30,
				})
			}),
		},
		ListPhotos: []gax.CallOption{
			gax.WithTimeout(60000 * time.Millisecond),
			gax.WithRetry(func() gax.Retryer {
				return gax.OnCodes([]codes.Code{
					codes.Unavailable,
					codes.DeadlineExceeded,
				}, gax.Backoff{
					Initial:    100 * time.Millisecond,
					Max:        60000 * time.Millisecond,
					Multiplier: 1.30,
				})
			}),
		},
		UpdatePhoto: []gax.CallOption{
			gax.WithTimeout(60000 * time.Millisecond),
			gax.WithRetry(func() gax.Retryer {
				return gax.OnCodes([]codes.Code{
					codes.Unavailable,
					codes.DeadlineExceeded,
				}, gax.Backoff{
					Initial:    100 * time.Millisecond,
					Max:        60000 * time.Millisecond,
					Multiplier: 1.30,
				})
			}),
		},
		BatchUpdatePhotos: []gax.CallOption{
			gax.WithTimeout(60000 * time.Millisecond),
			gax.WithRetry(func() gax.Retryer {
				return gax.OnCodes([]codes.Code{}, gax.Backoff{
					Initial:    100 * time.Millisecond,
					Max:        60000 * time.Millisecond,
					Multiplier: 1.30,
				})
			}),
		},
		DeletePhoto: []gax.CallOption{
			gax.WithTimeout(60000 * time.Millisecond),
			gax.WithRetry(func() gax.Retryer {
				return gax.OnCodes([]codes.Code{
					codes.Unavailable,
					codes.DeadlineExceeded,
				}, gax.Backoff{
					Initial:    100 * time.Millisecond,
					Max:        60000 * time.Millisecond,
					Multiplier: 1.30,
				})
			}),
		},
		BatchDeletePhotos:        []gax.CallOption{},
		StartPhotoSequenceUpload: []gax.CallOption{},
		CreatePhotoSequence:      []gax.CallOption{},
		GetPhotoSequence:         []gax.CallOption{},
		ListPhotoSequences:       []gax.CallOption{},
		DeletePhotoSequence:      []gax.CallOption{},
	}
}

func defaultStreetViewPublishRESTCallOptions() *StreetViewPublishCallOptions {
	return &StreetViewPublishCallOptions{
		StartUpload: []gax.CallOption{
			gax.WithTimeout(60000 * time.Millisecond),
		},
		CreatePhoto: []gax.CallOption{
			gax.WithTimeout(60000 * time.Millisecond),
		},
		GetPhoto: []gax.CallOption{
			gax.WithTimeout(60000 * time.Millisecond),
			gax.WithRetry(func() gax.Retryer {
				return gax.OnHTTPCodes(gax.Backoff{
					Initial:    100 * time.Millisecond,
					Max:        60000 * time.Millisecond,
					Multiplier: 1.30,
				},
					http.StatusServiceUnavailable,
					http.StatusGatewayTimeout)
			}),
		},
		BatchGetPhotos: []gax.CallOption{
			gax.WithTimeout(60000 * time.Millisecond),
			gax.WithRetry(func() gax.Retryer {
				return gax.OnHTTPCodes(gax.Backoff{
					Initial:    100 * time.Millisecond,
					Max:        60000 * time.Millisecond,
					Multiplier: 1.30,
				},
					http.StatusServiceUnavailable,
					http.StatusGatewayTimeout)
			}),
		},
		ListPhotos: []gax.CallOption{
			gax.WithTimeout(60000 * time.Millisecond),
			gax.WithRetry(func() gax.Retryer {
				return gax.OnHTTPCodes(gax.Backoff{
					Initial:    100 * time.Millisecond,
					Max:        60000 * time.Millisecond,
					Multiplier: 1.30,
				},
					http.StatusServiceUnavailable,
					http.StatusGatewayTimeout)
			}),
		},
		UpdatePhoto: []gax.CallOption{
			gax.WithTimeout(60000 * time.Millisecond),
			gax.WithRetry(func() gax.Retryer {
				return gax.OnHTTPCodes(gax.Backoff{
					Initial:    100 * time.Millisecond,
					Max:        60000 * time.Millisecond,
					Multiplier: 1.30,
				},
					http.StatusServiceUnavailable,
					http.StatusGatewayTimeout)
			}),
		},
		BatchUpdatePhotos: []gax.CallOption{
			gax.WithTimeout(60000 * time.Millisecond),
		},
		DeletePhoto: []gax.CallOption{
			gax.WithTimeout(60000 * time.Millisecond),
			gax.WithRetry(func() gax.Retryer {
				return gax.OnHTTPCodes(gax.Backoff{
					Initial:    100 * time.Millisecond,
					Max:        60000 * time.Millisecond,
					Multiplier: 1.30,
				},
					http.StatusServiceUnavailable,
					http.StatusGatewayTimeout)
			}),
		},
		BatchDeletePhotos:        []gax.CallOption{},
		StartPhotoSequenceUpload: []gax.CallOption{},
		CreatePhotoSequence:      []gax.CallOption{},
		GetPhotoSequence:         []gax.CallOption{},
		ListPhotoSequences:       []gax.CallOption{},
		DeletePhotoSequence:      []gax.CallOption{},
	}
}

// internalStreetViewPublishClient is an interface that defines the methods available from Street View Publish API.
type internalStreetViewPublishClient interface {
	Close() error
	setGoogleClientInfo(...string)
	Connection() *grpc.ClientConn
	StartUpload(context.Context, *emptypb.Empty, ...gax.CallOption) (*publishpb.UploadRef, error)
	CreatePhoto(context.Context, *publishpb.CreatePhotoRequest, ...gax.CallOption) (*publishpb.Photo, error)
	GetPhoto(context.Context, *publishpb.GetPhotoRequest, ...gax.CallOption) (*publishpb.Photo, error)
	BatchGetPhotos(context.Context, *publishpb.BatchGetPhotosRequest, ...gax.CallOption) (*publishpb.BatchGetPhotosResponse, error)
	ListPhotos(context.Context, *publishpb.ListPhotosRequest, ...gax.CallOption) *PhotoIterator
	UpdatePhoto(context.Context, *publishpb.UpdatePhotoRequest, ...gax.CallOption) (*publishpb.Photo, error)
	BatchUpdatePhotos(context.Context, *publishpb.BatchUpdatePhotosRequest, ...gax.CallOption) (*publishpb.BatchUpdatePhotosResponse, error)
	DeletePhoto(context.Context, *publishpb.DeletePhotoRequest, ...gax.CallOption) error
	BatchDeletePhotos(context.Context, *publishpb.BatchDeletePhotosRequest, ...gax.CallOption) (*publishpb.BatchDeletePhotosResponse, error)
	StartPhotoSequenceUpload(context.Context, *emptypb.Empty, ...gax.CallOption) (*publishpb.UploadRef, error)
	CreatePhotoSequence(context.Context, *publishpb.CreatePhotoSequenceRequest, ...gax.CallOption) (*CreatePhotoSequenceOperation, error)
	CreatePhotoSequenceOperation(name string) *CreatePhotoSequenceOperation
	GetPhotoSequence(context.Context, *publishpb.GetPhotoSequenceRequest, ...gax.CallOption) (*GetPhotoSequenceOperation, error)
	GetPhotoSequenceOperation(name string) *GetPhotoSequenceOperation
	ListPhotoSequences(context.Context, *publishpb.ListPhotoSequencesRequest, ...gax.CallOption) *OperationIterator
	DeletePhotoSequence(context.Context, *publishpb.DeletePhotoSequenceRequest, ...gax.CallOption) error
}

// StreetViewPublishClient is a client for interacting with Street View Publish API.
// Methods, except Close, may be called concurrently. However, fields must not be modified concurrently with method calls.
//
// Publishes and connects user-contributed photos on Street View.
type StreetViewPublishClient struct {
	// The internal transport-dependent client.
	internalClient internalStreetViewPublishClient

	// The call options for this service.
	CallOptions *StreetViewPublishCallOptions

	// LROClient is used internally to handle long-running operations.
	// It is exposed so that its CallOptions can be modified if required.
	// Users should not Close this client.
	LROClient *lroauto.OperationsClient
}

// Wrapper methods routed to the internal client.

// Close closes the connection to the API service. The user should invoke this when
// the client is no longer required.
func (c *StreetViewPublishClient) Close() error {
	return c.internalClient.Close()
}

// setGoogleClientInfo sets the name and version of the application in
// the `x-goog-api-client` header passed on each request. Intended for
// use by Google-written clients.
func (c *StreetViewPublishClient) setGoogleClientInfo(keyval ...string) {
	c.internalClient.setGoogleClientInfo(keyval...)
}

// Connection returns a connection to the API service.
//
// Deprecated: Connections are now pooled so this method does not always
// return the same resource.
func (c *StreetViewPublishClient) Connection() *grpc.ClientConn {
	return c.internalClient.Connection()
}

// StartUpload creates an upload session to start uploading photo bytes.  The method uses
// the upload URL of the returned
// UploadRef to upload the bytes for
// the [Photo][google.streetview.publish.v1.Photo (at http://google.streetview.publish.v1.Photo)].
//
// In addition to the photo requirements shown in
// https://support.google.com/maps/answer/7012050?ref_topic=6275604 (at https://support.google.com/maps/answer/7012050?ref_topic=6275604),
// the photo must meet the following requirements:
//
//	Photo Sphere XMP metadata must be included in the photo metadata. See
//	https://developers.google.com/streetview/spherical-metadata (at https://developers.google.com/streetview/spherical-metadata) for the
//	required fields.
//
//	The pixel size of the photo must meet the size requirements listed in
//	https://support.google.com/maps/answer/7012050?ref_topic=6275604 (at https://support.google.com/maps/answer/7012050?ref_topic=6275604), and
//	the photo must be a full 360 horizontally.
//
// After the upload completes, the method uses
// UploadRef with
// CreatePhoto
// to create the [Photo][google.streetview.publish.v1.Photo (at http://google.streetview.publish.v1.Photo)] object entry.
func (c *StreetViewPublishClient) StartUpload(ctx context.Context, req *emptypb.Empty, opts ...gax.CallOption) (*publishpb.UploadRef, error) {
	return c.internalClient.StartUpload(ctx, req, opts...)
}

// CreatePhoto after the client finishes uploading the photo with the returned
// UploadRef,
// CreatePhoto
// publishes the uploaded [Photo][google.streetview.publish.v1.Photo (at http://google.streetview.publish.v1.Photo)] to
// Street View on Google Maps.
//
// Currently, the only way to set heading, pitch, and roll in CreatePhoto is
// through the Photo Sphere XMP
// metadata (at https://developers.google.com/streetview/spherical-metadata) in
// the photo bytes. CreatePhoto ignores the  pose.heading, pose.pitch,
// pose.roll, pose.altitude, and pose.level fields in Pose.
//
// This method returns the following error codes:
//
//	google.rpc.Code.INVALID_ARGUMENT if
//	the request is malformed or if the uploaded photo is not a 360 photo.
//
//	google.rpc.Code.NOT_FOUND if the upload
//	reference does not exist.
//
//	google.rpc.Code.RESOURCE_EXHAUSTED
//	if the account has reached the storage limit.
func (c *StreetViewPublishClient) CreatePhoto(ctx context.Context, req *publishpb.CreatePhotoRequest, opts ...gax.CallOption) (*publishpb.Photo, error) {
	return c.internalClient.CreatePhoto(ctx, req, opts...)
}

// GetPhoto gets the metadata of the specified
// [Photo][google.streetview.publish.v1.Photo (at http://google.streetview.publish.v1.Photo)].
//
// This method returns the following error codes:
//
//	google.rpc.Code.PERMISSION_DENIED if
//	the requesting user did not create the requested
//	[Photo][google.streetview.publish.v1.Photo (at http://google.streetview.publish.v1.Photo)].
//
//	google.rpc.Code.NOT_FOUND if the requested
//	[Photo][google.streetview.publish.v1.Photo (at http://google.streetview.publish.v1.Photo)] does not exist.
//
//	google.rpc.Code.UNAVAILABLE if the
//	requested [Photo][google.streetview.publish.v1.Photo (at http://google.streetview.publish.v1.Photo)] is still being
//	indexed.
func (c *StreetViewPublishClient) GetPhoto(ctx context.Context, req *publishpb.GetPhotoRequest, opts ...gax.CallOption) (*publishpb.Photo, error) {
	return c.internalClient.GetPhoto(ctx, req, opts...)
}

// BatchGetPhotos gets the metadata of the specified
// [Photo][google.streetview.publish.v1.Photo (at http://google.streetview.publish.v1.Photo)] batch.
//
// Note that if
// BatchGetPhotos
// fails, either critical fields are missing or there is an authentication
// error. Even if
// BatchGetPhotos
// succeeds, individual photos in the batch may have failures.
// These failures are specified in each
// PhotoResponse.status
// in
// BatchGetPhotosResponse.results.
// See
// GetPhoto
// for specific failures that can occur per photo.
func (c *StreetViewPublishClient) BatchGetPhotos(ctx context.Context, req *publishpb.BatchGetPhotosRequest, opts ...gax.CallOption) (*publishpb.BatchGetPhotosResponse, error) {
	return c.internalClient.BatchGetPhotos(ctx, req, opts...)
}

// ListPhotos lists all the [Photos][google.streetview.publish.v1.Photo (at http://google.streetview.publish.v1.Photo)] that belong to
// the user.
//
// Note: Recently created photos that are still
// being indexed are not returned in the response.
func (c *StreetViewPublishClient) ListPhotos(ctx context.Context, req *publishpb.ListPhotosRequest, opts ...gax.CallOption) *PhotoIterator {
	return c.internalClient.ListPhotos(ctx, req, opts...)
}

// UpdatePhoto updates the metadata of a [Photo][google.streetview.publish.v1.Photo (at http://google.streetview.publish.v1.Photo)], such
// as pose, place association, connections, etc. Changing the pixels of a
// photo is not supported.
//
// Only the fields specified in the
// updateMask
// field are used. If updateMask is not present, the update applies to all
// fields.
//
// This method returns the following error codes:
//
//	google.rpc.Code.PERMISSION_DENIED if
//	the requesting user did not create the requested photo.
//
//	google.rpc.Code.INVALID_ARGUMENT if
//	the request is malformed.
//
//	google.rpc.Code.NOT_FOUND if the requested
//	photo does not exist.
//
//	google.rpc.Code.UNAVAILABLE if the
//	requested [Photo][google.streetview.publish.v1.Photo (at http://google.streetview.publish.v1.Photo)] is still being
//	indexed.
func (c *StreetViewPublishClient) UpdatePhoto(ctx context.Context, req *publishpb.UpdatePhotoRequest, opts ...gax.CallOption) (*publishpb.Photo, error) {
	return c.internalClient.UpdatePhoto(ctx, req, opts...)
}

// BatchUpdatePhotos updates the metadata of [Photos][google.streetview.publish.v1.Photo (at http://google.streetview.publish.v1.Photo)], such
// as pose, place association, connections, etc. Changing the pixels of photos
// is not supported.
//
// Note that if
// BatchUpdatePhotos
// fails, either critical fields are missing or there is an authentication
// error. Even if
// BatchUpdatePhotos
// succeeds, individual photos in the batch may have failures.
// These failures are specified in each
// PhotoResponse.status
// in
// BatchUpdatePhotosResponse.results.
// See
// UpdatePhoto
// for specific failures that can occur per photo.
//
// Only the fields specified in
// updateMask
// field are used. If updateMask is not present, the update applies to all
// fields.
//
// The number of
// UpdatePhotoRequest
// messages in a
// BatchUpdatePhotosRequest
// must not exceed 20.
//
// Note: To update
// Pose.altitude,
// Pose.latLngPair has to be
// filled as well. Otherwise, the request will fail.
func (c *StreetViewPublishClient) BatchUpdatePhotos(ctx context.Context, req *publishpb.BatchUpdatePhotosRequest, opts ...gax.CallOption) (*publishpb.BatchUpdatePhotosResponse, error) {
	return c.internalClient.BatchUpdatePhotos(ctx, req, opts...)
}

// DeletePhoto deletes a [Photo][google.streetview.publish.v1.Photo (at http://google.streetview.publish.v1.Photo)] and its metadata.
//
// This method returns the following error codes:
//
//	google.rpc.Code.PERMISSION_DENIED if
//	the requesting user did not create the requested photo.
//
//	google.rpc.Code.NOT_FOUND if the photo ID
//	does not exist.
func (c *StreetViewPublishClient) DeletePhoto(ctx context.Context, req *publishpb.DeletePhotoRequest, opts ...gax.CallOption) error {
	return c.internalClient.DeletePhoto(ctx, req, opts...)
}

// BatchDeletePhotos deletes a list of [Photos][google.streetview.publish.v1.Photo (at http://google.streetview.publish.v1.Photo)] and their
// metadata.
//
// Note that if
// BatchDeletePhotos
// fails, either critical fields are missing or there is an authentication
// error. Even if
// BatchDeletePhotos
// succeeds, individual photos in the batch may have failures.
// These failures are specified in each
// PhotoResponse.status
// in
// BatchDeletePhotosResponse.results.
// See
// DeletePhoto
// for specific failures that can occur per photo.
func (c *StreetViewPublishClient) BatchDeletePhotos(ctx context.Context, req *publishpb.BatchDeletePhotosRequest, opts ...gax.CallOption) (*publishpb.BatchDeletePhotosResponse, error) {
	return c.internalClient.BatchDeletePhotos(ctx, req, opts...)
}

// StartPhotoSequenceUpload creates an upload session to start uploading photo sequence data.
// The upload URL of the returned
// UploadRef is used to upload the
// data for the photoSequence.
//
// After the upload is complete, the
// UploadRef is used with
// CreatePhotoSequence
// to create the PhotoSequence
// object entry.
func (c *StreetViewPublishClient) StartPhotoSequenceUpload(ctx context.Context, req *emptypb.Empty, opts ...gax.CallOption) (*publishpb.UploadRef, error) {
	return c.internalClient.StartPhotoSequenceUpload(ctx, req, opts...)
}

// CreatePhotoSequence after the client finishes uploading the
// PhotoSequence with the
// returned UploadRef,
// CreatePhotoSequence
// extracts a sequence of 360 photos from a video or Extensible Device
// Metadata (XDM, http://www.xdm.org/ (at http://www.xdm.org/)) to be published to Street View on
// Google Maps.
//
// CreatePhotoSequence returns an Operation,
// with the PhotoSequence Id set
// in the Operation.name field.
//
// This method returns the following error codes:
//
//	google.rpc.Code.INVALID_ARGUMENT if
//	the request is malformed.
//
//	google.rpc.Code.NOT_FOUND if the upload
//	reference does not exist.
func (c *StreetViewPublishClient) CreatePhotoSequence(ctx context.Context, req *publishpb.CreatePhotoSequenceRequest, opts ...gax.CallOption) (*CreatePhotoSequenceOperation, error) {
	return c.internalClient.CreatePhotoSequence(ctx, req, opts...)
}

// CreatePhotoSequenceOperation returns a new CreatePhotoSequenceOperation from a given name.
// The name must be that of a previously created CreatePhotoSequenceOperation, possibly from a different process.
func (c *StreetViewPublishClient) CreatePhotoSequenceOperation(name string) *CreatePhotoSequenceOperation {
	return c.internalClient.CreatePhotoSequenceOperation(name)
}

// GetPhotoSequence gets the metadata of the specified
// PhotoSequence via the
// Operation interface.
//
// This method returns the following three types of responses:
//
//	Operation.done = false, if the processing of
//	PhotoSequence is not
//	finished yet.
//
//	Operation.done = true and Operation.error is populated, if there was
//	an error in processing.
//
//	Operation.done = true and Operation.response is poulated, which
//	contains a PhotoSequence
//	message.
//
// This method returns the following error codes:
//
//	google.rpc.Code.PERMISSION_DENIED if
//	the requesting user did not create the requested
//	PhotoSequence.
//
//	google.rpc.Code.NOT_FOUND if the requested
//	PhotoSequence does not exist.
func (c *StreetViewPublishClient) GetPhotoSequence(ctx context.Context, req *publishpb.GetPhotoSequenceRequest, opts ...gax.CallOption) (*GetPhotoSequenceOperation, error) {
	return c.internalClient.GetPhotoSequence(ctx, req, opts...)
}

// GetPhotoSequenceOperation returns a new GetPhotoSequenceOperation from a given name.
// The name must be that of a previously created GetPhotoSequenceOperation, possibly from a different process.
func (c *StreetViewPublishClient) GetPhotoSequenceOperation(name string) *GetPhotoSequenceOperation {
	return c.internalClient.GetPhotoSequenceOperation(name)
}

// ListPhotoSequences lists all the PhotoSequences
// that belong to the user, in descending CreatePhotoSequence timestamp order.
func (c *StreetViewPublishClient) ListPhotoSequences(ctx context.Context, req *publishpb.ListPhotoSequencesRequest, opts ...gax.CallOption) *OperationIterator {
	return c.internalClient.ListPhotoSequences(ctx, req, opts...)
}

// DeletePhotoSequence deletes a PhotoSequence and
// its metadata.
//
// This method returns the following error codes:
//
//	google.rpc.Code.PERMISSION_DENIED if
//	the requesting user did not create the requested photo sequence.
//
//	google.rpc.Code.NOT_FOUND if the photo
//	sequence ID does not exist.
//
//	google.rpc.Code.FAILED_PRECONDITION if the photo sequence ID is not
//	yet finished processing.
func (c *StreetViewPublishClient) DeletePhotoSequence(ctx context.Context, req *publishpb.DeletePhotoSequenceRequest, opts ...gax.CallOption) error {
	return c.internalClient.DeletePhotoSequence(ctx, req, opts...)
}

// streetViewPublishGRPCClient is a client for interacting with Street View Publish API over gRPC transport.
//
// Methods, except Close, may be called concurrently. However, fields must not be modified concurrently with method calls.
type streetViewPublishGRPCClient struct {
	// Connection pool of gRPC connections to the service.
	connPool gtransport.ConnPool

	// Points back to the CallOptions field of the containing StreetViewPublishClient
	CallOptions **StreetViewPublishCallOptions

	// The gRPC API client.
	streetViewPublishClient publishpb.StreetViewPublishServiceClient

	// LROClient is used internally to handle long-running operations.
	// It is exposed so that its CallOptions can be modified if required.
	// Users should not Close this client.
	LROClient **lroauto.OperationsClient

	// The x-goog-* metadata to be sent with each request.
	xGoogHeaders []string
}

// NewStreetViewPublishClient creates a new street view publish service client based on gRPC.
// The returned client must be Closed when it is done being used to clean up its underlying connections.
//
// Publishes and connects user-contributed photos on Street View.
func NewStreetViewPublishClient(ctx context.Context, opts ...option.ClientOption) (*StreetViewPublishClient, error) {
	clientOpts := defaultStreetViewPublishGRPCClientOptions()
	if newStreetViewPublishClientHook != nil {
		hookOpts, err := newStreetViewPublishClientHook(ctx, clientHookParams{})
		if err != nil {
			return nil, err
		}
		clientOpts = append(clientOpts, hookOpts...)
	}

	connPool, err := gtransport.DialPool(ctx, append(clientOpts, opts...)...)
	if err != nil {
		return nil, err
	}
	client := StreetViewPublishClient{CallOptions: defaultStreetViewPublishCallOptions()}

	c := &streetViewPublishGRPCClient{
		connPool:                connPool,
		streetViewPublishClient: publishpb.NewStreetViewPublishServiceClient(connPool),
		CallOptions:             &client.CallOptions,
	}
	c.setGoogleClientInfo()

	client.internalClient = c

	client.LROClient, err = lroauto.NewOperationsClient(ctx, gtransport.WithConnPool(connPool))
	if err != nil {
		// This error "should not happen", since we are just reusing old connection pool
		// and never actually need to dial.
		// If this does happen, we could leak connp. However, we cannot close conn:
		// If the user invoked the constructor with option.WithGRPCConn,
		// we would close a connection that's still in use.
		// TODO: investigate error conditions.
		return nil, err
	}
	c.LROClient = &client.LROClient
	return &client, nil
}

// Connection returns a connection to the API service.
//
// Deprecated: Connections are now pooled so this method does not always
// return the same resource.
func (c *streetViewPublishGRPCClient) Connection() *grpc.ClientConn {
	return c.connPool.Conn()
}

// setGoogleClientInfo sets the name and version of the application in
// the `x-goog-api-client` header passed on each request. Intended for
// use by Google-written clients.
func (c *streetViewPublishGRPCClient) setGoogleClientInfo(keyval ...string) {
	kv := append([]string{"gl-go", gax.GoVersion}, keyval...)
	kv = append(kv, "gapic", getVersionClient(), "gax", gax.Version, "grpc", grpc.Version)
	c.xGoogHeaders = []string{"x-goog-api-client", gax.XGoogHeader(kv...)}
}

// Close closes the connection to the API service. The user should invoke this when
// the client is no longer required.
func (c *streetViewPublishGRPCClient) Close() error {
	return c.connPool.Close()
}

// Methods, except Close, may be called concurrently. However, fields must not be modified concurrently with method calls.
type streetViewPublishRESTClient struct {
	// The http endpoint to connect to.
	endpoint string

	// The http client.
	httpClient *http.Client

	// LROClient is used internally to handle long-running operations.
	// It is exposed so that its CallOptions can be modified if required.
	// Users should not Close this client.
	LROClient **lroauto.OperationsClient

	// The x-goog-* headers to be sent with each request.
	xGoogHeaders []string

	// Points back to the CallOptions field of the containing StreetViewPublishClient
	CallOptions **StreetViewPublishCallOptions
}

// NewStreetViewPublishRESTClient creates a new street view publish service rest client.
//
// Publishes and connects user-contributed photos on Street View.
func NewStreetViewPublishRESTClient(ctx context.Context, opts ...option.ClientOption) (*StreetViewPublishClient, error) {
	clientOpts := append(defaultStreetViewPublishRESTClientOptions(), opts...)
	httpClient, endpoint, err := httptransport.NewClient(ctx, clientOpts...)
	if err != nil {
		return nil, err
	}

	callOpts := defaultStreetViewPublishRESTCallOptions()
	c := &streetViewPublishRESTClient{
		endpoint:    endpoint,
		httpClient:  httpClient,
		CallOptions: &callOpts,
	}
	c.setGoogleClientInfo()

	lroOpts := []option.ClientOption{
		option.WithHTTPClient(httpClient),
		option.WithEndpoint(endpoint),
	}
	opClient, err := lroauto.NewOperationsRESTClient(ctx, lroOpts...)
	if err != nil {
		return nil, err
	}
	c.LROClient = &opClient

	return &StreetViewPublishClient{internalClient: c, CallOptions: callOpts}, nil
}

func defaultStreetViewPublishRESTClientOptions() []option.ClientOption {
	return []option.ClientOption{
		internaloption.WithDefaultEndpoint("https://streetviewpublish.googleapis.com"),
		internaloption.WithDefaultEndpointTemplate("https://streetviewpublish.UNIVERSE_DOMAIN"),
		internaloption.WithDefaultMTLSEndpoint("https://streetviewpublish.mtls.googleapis.com"),
		internaloption.WithDefaultUniverseDomain("googleapis.com"),
		internaloption.WithDefaultAudience("https://streetviewpublish.googleapis.com/"),
		internaloption.WithDefaultScopes(DefaultAuthScopes()...),
	}
}

// setGoogleClientInfo sets the name and version of the application in
// the `x-goog-api-client` header passed on each request. Intended for
// use by Google-written clients.
func (c *streetViewPublishRESTClient) setGoogleClientInfo(keyval ...string) {
	kv := append([]string{"gl-go", gax.GoVersion}, keyval...)
	kv = append(kv, "gapic", getVersionClient(), "gax", gax.Version, "rest", "UNKNOWN")
	c.xGoogHeaders = []string{"x-goog-api-client", gax.XGoogHeader(kv...)}
}

// Close closes the connection to the API service. The user should invoke this when
// the client is no longer required.
func (c *streetViewPublishRESTClient) Close() error {
	// Replace httpClient with nil to force cleanup.
	c.httpClient = nil
	return nil
}

// Connection returns a connection to the API service.
//
// Deprecated: This method always returns nil.
func (c *streetViewPublishRESTClient) Connection() *grpc.ClientConn {
	return nil
}
func (c *streetViewPublishGRPCClient) StartUpload(ctx context.Context, req *emptypb.Empty, opts ...gax.CallOption) (*publishpb.UploadRef, error) {
	ctx = gax.InsertMetadataIntoOutgoingContext(ctx, c.xGoogHeaders...)
	opts = append((*c.CallOptions).StartUpload[0:len((*c.CallOptions).StartUpload):len((*c.CallOptions).StartUpload)], opts...)
	var resp *publishpb.UploadRef
	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		var err error
		resp, err = c.streetViewPublishClient.StartUpload(ctx, req, settings.GRPC...)
		return err
	}, opts...)
	if err != nil {
		return nil, err
	}
	return resp, nil
}

func (c *streetViewPublishGRPCClient) CreatePhoto(ctx context.Context, req *publishpb.CreatePhotoRequest, opts ...gax.CallOption) (*publishpb.Photo, error) {
	ctx = gax.InsertMetadataIntoOutgoingContext(ctx, c.xGoogHeaders...)
	opts = append((*c.CallOptions).CreatePhoto[0:len((*c.CallOptions).CreatePhoto):len((*c.CallOptions).CreatePhoto)], opts...)
	var resp *publishpb.Photo
	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		var err error
		resp, err = c.streetViewPublishClient.CreatePhoto(ctx, req, settings.GRPC...)
		return err
	}, opts...)
	if err != nil {
		return nil, err
	}
	return resp, nil
}

func (c *streetViewPublishGRPCClient) GetPhoto(ctx context.Context, req *publishpb.GetPhotoRequest, opts ...gax.CallOption) (*publishpb.Photo, error) {
	hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "photo_id", url.QueryEscape(req.GetPhotoId()))}

	hds = append(c.xGoogHeaders, hds...)
	ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...)
	opts = append((*c.CallOptions).GetPhoto[0:len((*c.CallOptions).GetPhoto):len((*c.CallOptions).GetPhoto)], opts...)
	var resp *publishpb.Photo
	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		var err error
		resp, err = c.streetViewPublishClient.GetPhoto(ctx, req, settings.GRPC...)
		return err
	}, opts...)
	if err != nil {
		return nil, err
	}
	return resp, nil
}

func (c *streetViewPublishGRPCClient) BatchGetPhotos(ctx context.Context, req *publishpb.BatchGetPhotosRequest, opts ...gax.CallOption) (*publishpb.BatchGetPhotosResponse, error) {
	ctx = gax.InsertMetadataIntoOutgoingContext(ctx, c.xGoogHeaders...)
	opts = append((*c.CallOptions).BatchGetPhotos[0:len((*c.CallOptions).BatchGetPhotos):len((*c.CallOptions).BatchGetPhotos)], opts...)
	var resp *publishpb.BatchGetPhotosResponse
	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		var err error
		resp, err = c.streetViewPublishClient.BatchGetPhotos(ctx, req, settings.GRPC...)
		return err
	}, opts...)
	if err != nil {
		return nil, err
	}
	return resp, nil
}

func (c *streetViewPublishGRPCClient) ListPhotos(ctx context.Context, req *publishpb.ListPhotosRequest, opts ...gax.CallOption) *PhotoIterator {
	ctx = gax.InsertMetadataIntoOutgoingContext(ctx, c.xGoogHeaders...)
	opts = append((*c.CallOptions).ListPhotos[0:len((*c.CallOptions).ListPhotos):len((*c.CallOptions).ListPhotos)], opts...)
	it := &PhotoIterator{}
	req = proto.Clone(req).(*publishpb.ListPhotosRequest)
	it.InternalFetch = func(pageSize int, pageToken string) ([]*publishpb.Photo, string, error) {
		resp := &publishpb.ListPhotosResponse{}
		if pageToken != "" {
			req.PageToken = pageToken
		}
		if pageSize > math.MaxInt32 {
			req.PageSize = math.MaxInt32
		} else if pageSize != 0 {
			req.PageSize = int32(pageSize)
		}
		err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
			var err error
			resp, err = c.streetViewPublishClient.ListPhotos(ctx, req, settings.GRPC...)
			return err
		}, opts...)
		if err != nil {
			return nil, "", err
		}

		it.Response = resp
		return resp.GetPhotos(), resp.GetNextPageToken(), nil
	}
	fetch := func(pageSize int, pageToken string) (string, error) {
		items, nextPageToken, err := it.InternalFetch(pageSize, pageToken)
		if err != nil {
			return "", err
		}
		it.items = append(it.items, items...)
		return nextPageToken, nil
	}

	it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf)
	it.pageInfo.MaxSize = int(req.GetPageSize())
	it.pageInfo.Token = req.GetPageToken()

	return it
}

func (c *streetViewPublishGRPCClient) UpdatePhoto(ctx context.Context, req *publishpb.UpdatePhotoRequest, opts ...gax.CallOption) (*publishpb.Photo, error) {
	hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "photo.photo_id.id", url.QueryEscape(req.GetPhoto().GetPhotoId().GetId()))}

	hds = append(c.xGoogHeaders, hds...)
	ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...)
	opts = append((*c.CallOptions).UpdatePhoto[0:len((*c.CallOptions).UpdatePhoto):len((*c.CallOptions).UpdatePhoto)], opts...)
	var resp *publishpb.Photo
	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		var err error
		resp, err = c.streetViewPublishClient.UpdatePhoto(ctx, req, settings.GRPC...)
		return err
	}, opts...)
	if err != nil {
		return nil, err
	}
	return resp, nil
}

func (c *streetViewPublishGRPCClient) BatchUpdatePhotos(ctx context.Context, req *publishpb.BatchUpdatePhotosRequest, opts ...gax.CallOption) (*publishpb.BatchUpdatePhotosResponse, error) {
	ctx = gax.InsertMetadataIntoOutgoingContext(ctx, c.xGoogHeaders...)
	opts = append((*c.CallOptions).BatchUpdatePhotos[0:len((*c.CallOptions).BatchUpdatePhotos):len((*c.CallOptions).BatchUpdatePhotos)], opts...)
	var resp *publishpb.BatchUpdatePhotosResponse
	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		var err error
		resp, err = c.streetViewPublishClient.BatchUpdatePhotos(ctx, req, settings.GRPC...)
		return err
	}, opts...)
	if err != nil {
		return nil, err
	}
	return resp, nil
}

func (c *streetViewPublishGRPCClient) DeletePhoto(ctx context.Context, req *publishpb.DeletePhotoRequest, opts ...gax.CallOption) error {
	hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "photo_id", url.QueryEscape(req.GetPhotoId()))}

	hds = append(c.xGoogHeaders, hds...)
	ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...)
	opts = append((*c.CallOptions).DeletePhoto[0:len((*c.CallOptions).DeletePhoto):len((*c.CallOptions).DeletePhoto)], opts...)
	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		var err error
		_, err = c.streetViewPublishClient.DeletePhoto(ctx, req, settings.GRPC...)
		return err
	}, opts...)
	return err
}

func (c *streetViewPublishGRPCClient) BatchDeletePhotos(ctx context.Context, req *publishpb.BatchDeletePhotosRequest, opts ...gax.CallOption) (*publishpb.BatchDeletePhotosResponse, error) {
	ctx = gax.InsertMetadataIntoOutgoingContext(ctx, c.xGoogHeaders...)
	opts = append((*c.CallOptions).BatchDeletePhotos[0:len((*c.CallOptions).BatchDeletePhotos):len((*c.CallOptions).BatchDeletePhotos)], opts...)
	var resp *publishpb.BatchDeletePhotosResponse
	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		var err error
		resp, err = c.streetViewPublishClient.BatchDeletePhotos(ctx, req, settings.GRPC...)
		return err
	}, opts...)
	if err != nil {
		return nil, err
	}
	return resp, nil
}

func (c *streetViewPublishGRPCClient) StartPhotoSequenceUpload(ctx context.Context, req *emptypb.Empty, opts ...gax.CallOption) (*publishpb.UploadRef, error) {
	ctx = gax.InsertMetadataIntoOutgoingContext(ctx, c.xGoogHeaders...)
	opts = append((*c.CallOptions).StartPhotoSequenceUpload[0:len((*c.CallOptions).StartPhotoSequenceUpload):len((*c.CallOptions).StartPhotoSequenceUpload)], opts...)
	var resp *publishpb.UploadRef
	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		var err error
		resp, err = c.streetViewPublishClient.StartPhotoSequenceUpload(ctx, req, settings.GRPC...)
		return err
	}, opts...)
	if err != nil {
		return nil, err
	}
	return resp, nil
}

func (c *streetViewPublishGRPCClient) CreatePhotoSequence(ctx context.Context, req *publishpb.CreatePhotoSequenceRequest, opts ...gax.CallOption) (*CreatePhotoSequenceOperation, error) {
	ctx = gax.InsertMetadataIntoOutgoingContext(ctx, c.xGoogHeaders...)
	opts = append((*c.CallOptions).CreatePhotoSequence[0:len((*c.CallOptions).CreatePhotoSequence):len((*c.CallOptions).CreatePhotoSequence)], opts...)
	var resp *longrunningpb.Operation
	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		var err error
		resp, err = c.streetViewPublishClient.CreatePhotoSequence(ctx, req, settings.GRPC...)
		return err
	}, opts...)
	if err != nil {
		return nil, err
	}
	return &CreatePhotoSequenceOperation{
		lro: longrunning.InternalNewOperation(*c.LROClient, resp),
	}, nil
}

func (c *streetViewPublishGRPCClient) GetPhotoSequence(ctx context.Context, req *publishpb.GetPhotoSequenceRequest, opts ...gax.CallOption) (*GetPhotoSequenceOperation, error) {
	hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "sequence_id", url.QueryEscape(req.GetSequenceId()))}

	hds = append(c.xGoogHeaders, hds...)
	ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...)
	opts = append((*c.CallOptions).GetPhotoSequence[0:len((*c.CallOptions).GetPhotoSequence):len((*c.CallOptions).GetPhotoSequence)], opts...)
	var resp *longrunningpb.Operation
	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		var err error
		resp, err = c.streetViewPublishClient.GetPhotoSequence(ctx, req, settings.GRPC...)
		return err
	}, opts...)
	if err != nil {
		return nil, err
	}
	return &GetPhotoSequenceOperation{
		lro: longrunning.InternalNewOperation(*c.LROClient, resp),
	}, nil
}

func (c *streetViewPublishGRPCClient) ListPhotoSequences(ctx context.Context, req *publishpb.ListPhotoSequencesRequest, opts ...gax.CallOption) *OperationIterator {
	ctx = gax.InsertMetadataIntoOutgoingContext(ctx, c.xGoogHeaders...)
	opts = append((*c.CallOptions).ListPhotoSequences[0:len((*c.CallOptions).ListPhotoSequences):len((*c.CallOptions).ListPhotoSequences)], opts...)
	it := &OperationIterator{}
	req = proto.Clone(req).(*publishpb.ListPhotoSequencesRequest)
	it.InternalFetch = func(pageSize int, pageToken string) ([]*longrunningpb.Operation, string, error) {
		resp := &publishpb.ListPhotoSequencesResponse{}
		if pageToken != "" {
			req.PageToken = pageToken
		}
		if pageSize > math.MaxInt32 {
			req.PageSize = math.MaxInt32
		} else if pageSize != 0 {
			req.PageSize = int32(pageSize)
		}
		err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
			var err error
			resp, err = c.streetViewPublishClient.ListPhotoSequences(ctx, req, settings.GRPC...)
			return err
		}, opts...)
		if err != nil {
			return nil, "", err
		}

		it.Response = resp
		return resp.GetPhotoSequences(), resp.GetNextPageToken(), nil
	}
	fetch := func(pageSize int, pageToken string) (string, error) {
		items, nextPageToken, err := it.InternalFetch(pageSize, pageToken)
		if err != nil {
			return "", err
		}
		it.items = append(it.items, items...)
		return nextPageToken, nil
	}

	it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf)
	it.pageInfo.MaxSize = int(req.GetPageSize())
	it.pageInfo.Token = req.GetPageToken()

	return it
}

func (c *streetViewPublishGRPCClient) DeletePhotoSequence(ctx context.Context, req *publishpb.DeletePhotoSequenceRequest, opts ...gax.CallOption) error {
	hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "sequence_id", url.QueryEscape(req.GetSequenceId()))}

	hds = append(c.xGoogHeaders, hds...)
	ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...)
	opts = append((*c.CallOptions).DeletePhotoSequence[0:len((*c.CallOptions).DeletePhotoSequence):len((*c.CallOptions).DeletePhotoSequence)], opts...)
	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		var err error
		_, err = c.streetViewPublishClient.DeletePhotoSequence(ctx, req, settings.GRPC...)
		return err
	}, opts...)
	return err
}

// StartUpload creates an upload session to start uploading photo bytes.  The method uses
// the upload URL of the returned
// UploadRef to upload the bytes for
// the [Photo][google.streetview.publish.v1.Photo (at http://google.streetview.publish.v1.Photo)].
//
// In addition to the photo requirements shown in
// https://support.google.com/maps/answer/7012050?ref_topic=6275604 (at https://support.google.com/maps/answer/7012050?ref_topic=6275604),
// the photo must meet the following requirements:
//
//	Photo Sphere XMP metadata must be included in the photo metadata. See
//	https://developers.google.com/streetview/spherical-metadata (at https://developers.google.com/streetview/spherical-metadata) for the
//	required fields.
//
//	The pixel size of the photo must meet the size requirements listed in
//	https://support.google.com/maps/answer/7012050?ref_topic=6275604 (at https://support.google.com/maps/answer/7012050?ref_topic=6275604), and
//	the photo must be a full 360 horizontally.
//
// After the upload completes, the method uses
// UploadRef with
// CreatePhoto
// to create the [Photo][google.streetview.publish.v1.Photo (at http://google.streetview.publish.v1.Photo)] object entry.
func (c *streetViewPublishRESTClient) StartUpload(ctx context.Context, req *emptypb.Empty, opts ...gax.CallOption) (*publishpb.UploadRef, error) {
	m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true}
	jsonReq, err := m.Marshal(req)
	if err != nil {
		return nil, err
	}

	baseUrl, err := url.Parse(c.endpoint)
	if err != nil {
		return nil, err
	}
	baseUrl.Path += fmt.Sprintf("/v1/photo:startUpload")

	params := url.Values{}
	params.Add("$alt", "json;enum-encoding=int")

	baseUrl.RawQuery = params.Encode()

	// Build HTTP headers from client and context metadata.
	hds := append(c.xGoogHeaders, "Content-Type", "application/json")
	headers := gax.BuildHeaders(ctx, hds...)
	opts = append((*c.CallOptions).StartUpload[0:len((*c.CallOptions).StartUpload):len((*c.CallOptions).StartUpload)], opts...)
	unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true}
	resp := &publishpb.UploadRef{}
	e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		if settings.Path != "" {
			baseUrl.Path = settings.Path
		}
		httpReq, err := http.NewRequest("POST", baseUrl.String(), bytes.NewReader(jsonReq))
		if err != nil {
			return err
		}
		httpReq = httpReq.WithContext(ctx)
		httpReq.Header = headers

		httpRsp, err := c.httpClient.Do(httpReq)
		if err != nil {
			return err
		}
		defer httpRsp.Body.Close()

		if err = googleapi.CheckResponse(httpRsp); err != nil {
			return err
		}

		buf, err := io.ReadAll(httpRsp.Body)
		if err != nil {
			return err
		}

		if err := unm.Unmarshal(buf, resp); err != nil {
			return err
		}

		return nil
	}, opts...)
	if e != nil {
		return nil, e
	}
	return resp, nil
}

// CreatePhoto after the client finishes uploading the photo with the returned
// UploadRef,
// CreatePhoto
// publishes the uploaded [Photo][google.streetview.publish.v1.Photo (at http://google.streetview.publish.v1.Photo)] to
// Street View on Google Maps.
//
// Currently, the only way to set heading, pitch, and roll in CreatePhoto is
// through the Photo Sphere XMP
// metadata (at https://developers.google.com/streetview/spherical-metadata) in
// the photo bytes. CreatePhoto ignores the  pose.heading, pose.pitch,
// pose.roll, pose.altitude, and pose.level fields in Pose.
//
// This method returns the following error codes:
//
//	google.rpc.Code.INVALID_ARGUMENT if
//	the request is malformed or if the uploaded photo is not a 360 photo.
//
//	google.rpc.Code.NOT_FOUND if the upload
//	reference does not exist.
//
//	google.rpc.Code.RESOURCE_EXHAUSTED
//	if the account has reached the storage limit.
func (c *streetViewPublishRESTClient) CreatePhoto(ctx context.Context, req *publishpb.CreatePhotoRequest, opts ...gax.CallOption) (*publishpb.Photo, error) {
	m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true}
	body := req.GetPhoto()
	jsonReq, err := m.Marshal(body)
	if err != nil {
		return nil, err
	}

	baseUrl, err := url.Parse(c.endpoint)
	if err != nil {
		return nil, err
	}
	baseUrl.Path += fmt.Sprintf("/v1/photo")

	params := url.Values{}
	params.Add("$alt", "json;enum-encoding=int")

	baseUrl.RawQuery = params.Encode()

	// Build HTTP headers from client and context metadata.
	hds := append(c.xGoogHeaders, "Content-Type", "application/json")
	headers := gax.BuildHeaders(ctx, hds...)
	opts = append((*c.CallOptions).CreatePhoto[0:len((*c.CallOptions).CreatePhoto):len((*c.CallOptions).CreatePhoto)], opts...)
	unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true}
	resp := &publishpb.Photo{}
	e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		if settings.Path != "" {
			baseUrl.Path = settings.Path
		}
		httpReq, err := http.NewRequest("POST", baseUrl.String(), bytes.NewReader(jsonReq))
		if err != nil {
			return err
		}
		httpReq = httpReq.WithContext(ctx)
		httpReq.Header = headers

		httpRsp, err := c.httpClient.Do(httpReq)
		if err != nil {
			return err
		}
		defer httpRsp.Body.Close()

		if err = googleapi.CheckResponse(httpRsp); err != nil {
			return err
		}

		buf, err := io.ReadAll(httpRsp.Body)
		if err != nil {
			return err
		}

		if err := unm.Unmarshal(buf, resp); err != nil {
			return err
		}

		return nil
	}, opts...)
	if e != nil {
		return nil, e
	}
	return resp, nil
}

// GetPhoto gets the metadata of the specified
// [Photo][google.streetview.publish.v1.Photo (at http://google.streetview.publish.v1.Photo)].
//
// This method returns the following error codes:
//
//	google.rpc.Code.PERMISSION_DENIED if
//	the requesting user did not create the requested
//	[Photo][google.streetview.publish.v1.Photo (at http://google.streetview.publish.v1.Photo)].
//
//	google.rpc.Code.NOT_FOUND if the requested
//	[Photo][google.streetview.publish.v1.Photo (at http://google.streetview.publish.v1.Photo)] does not exist.
//
//	google.rpc.Code.UNAVAILABLE if the
//	requested [Photo][google.streetview.publish.v1.Photo (at http://google.streetview.publish.v1.Photo)] is still being
//	indexed.
func (c *streetViewPublishRESTClient) GetPhoto(ctx context.Context, req *publishpb.GetPhotoRequest, opts ...gax.CallOption) (*publishpb.Photo, error) {
	baseUrl, err := url.Parse(c.endpoint)
	if err != nil {
		return nil, err
	}
	baseUrl.Path += fmt.Sprintf("/v1/photo/%v", req.GetPhotoId())

	params := url.Values{}
	params.Add("$alt", "json;enum-encoding=int")
	if req.GetLanguageCode() != "" {
		params.Add("languageCode", fmt.Sprintf("%v", req.GetLanguageCode()))
	}
	params.Add("view", fmt.Sprintf("%v", req.GetView()))

	baseUrl.RawQuery = params.Encode()

	// Build HTTP headers from client and context metadata.
	hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "photo_id", url.QueryEscape(req.GetPhotoId()))}

	hds = append(c.xGoogHeaders, hds...)
	hds = append(hds, "Content-Type", "application/json")
	headers := gax.BuildHeaders(ctx, hds...)
	opts = append((*c.CallOptions).GetPhoto[0:len((*c.CallOptions).GetPhoto):len((*c.CallOptions).GetPhoto)], opts...)
	unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true}
	resp := &publishpb.Photo{}
	e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		if settings.Path != "" {
			baseUrl.Path = settings.Path
		}
		httpReq, err := http.NewRequest("GET", baseUrl.String(), nil)
		if err != nil {
			return err
		}
		httpReq = httpReq.WithContext(ctx)
		httpReq.Header = headers

		httpRsp, err := c.httpClient.Do(httpReq)
		if err != nil {
			return err
		}
		defer httpRsp.Body.Close()

		if err = googleapi.CheckResponse(httpRsp); err != nil {
			return err
		}

		buf, err := io.ReadAll(httpRsp.Body)
		if err != nil {
			return err
		}

		if err := unm.Unmarshal(buf, resp); err != nil {
			return err
		}

		return nil
	}, opts...)
	if e != nil {
		return nil, e
	}
	return resp, nil
}

// BatchGetPhotos gets the metadata of the specified
// [Photo][google.streetview.publish.v1.Photo (at http://google.streetview.publish.v1.Photo)] batch.
//
// Note that if
// BatchGetPhotos
// fails, either critical fields are missing or there is an authentication
// error. Even if
// BatchGetPhotos
// succeeds, individual photos in the batch may have failures.
// These failures are specified in each
// PhotoResponse.status
// in
// BatchGetPhotosResponse.results.
// See
// GetPhoto
// for specific failures that can occur per photo.
func (c *streetViewPublishRESTClient) BatchGetPhotos(ctx context.Context, req *publishpb.BatchGetPhotosRequest, opts ...gax.CallOption) (*publishpb.BatchGetPhotosResponse, error) {
	baseUrl, err := url.Parse(c.endpoint)
	if err != nil {
		return nil, err
	}
	baseUrl.Path += fmt.Sprintf("/v1/photos:batchGet")

	params := url.Values{}
	params.Add("$alt", "json;enum-encoding=int")
	if req.GetLanguageCode() != "" {
		params.Add("languageCode", fmt.Sprintf("%v", req.GetLanguageCode()))
	}
	if items := req.GetPhotoIds(); len(items) > 0 {
		for _, item := range items {
			params.Add("photoIds", fmt.Sprintf("%v", item))
		}
	}
	params.Add("view", fmt.Sprintf("%v", req.GetView()))

	baseUrl.RawQuery = params.Encode()

	// Build HTTP headers from client and context metadata.
	hds := append(c.xGoogHeaders, "Content-Type", "application/json")
	headers := gax.BuildHeaders(ctx, hds...)
	opts = append((*c.CallOptions).BatchGetPhotos[0:len((*c.CallOptions).BatchGetPhotos):len((*c.CallOptions).BatchGetPhotos)], opts...)
	unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true}
	resp := &publishpb.BatchGetPhotosResponse{}
	e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		if settings.Path != "" {
			baseUrl.Path = settings.Path
		}
		httpReq, err := http.NewRequest("GET", baseUrl.String(), nil)
		if err != nil {
			return err
		}
		httpReq = httpReq.WithContext(ctx)
		httpReq.Header = headers

		httpRsp, err := c.httpClient.Do(httpReq)
		if err != nil {
			return err
		}
		defer httpRsp.Body.Close()

		if err = googleapi.CheckResponse(httpRsp); err != nil {
			return err
		}

		buf, err := io.ReadAll(httpRsp.Body)
		if err != nil {
			return err
		}

		if err := unm.Unmarshal(buf, resp); err != nil {
			return err
		}

		return nil
	}, opts...)
	if e != nil {
		return nil, e
	}
	return resp, nil
}

// ListPhotos lists all the [Photos][google.streetview.publish.v1.Photo (at http://google.streetview.publish.v1.Photo)] that belong to
// the user.
//
// Note: Recently created photos that are still
// being indexed are not returned in the response.
func (c *streetViewPublishRESTClient) ListPhotos(ctx context.Context, req *publishpb.ListPhotosRequest, opts ...gax.CallOption) *PhotoIterator {
	it := &PhotoIterator{}
	req = proto.Clone(req).(*publishpb.ListPhotosRequest)
	unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true}
	it.InternalFetch = func(pageSize int, pageToken string) ([]*publishpb.Photo, string, error) {
		resp := &publishpb.ListPhotosResponse{}
		if pageToken != "" {
			req.PageToken = pageToken
		}
		if pageSize > math.MaxInt32 {
			req.PageSize = math.MaxInt32
		} else if pageSize != 0 {
			req.PageSize = int32(pageSize)
		}
		baseUrl, err := url.Parse(c.endpoint)
		if err != nil {
			return nil, "", err
		}
		baseUrl.Path += fmt.Sprintf("/v1/photos")

		params := url.Values{}
		params.Add("$alt", "json;enum-encoding=int")
		if req.GetFilter() != "" {
			params.Add("filter", fmt.Sprintf("%v", req.GetFilter()))
		}
		if req.GetLanguageCode() != "" {
			params.Add("languageCode", fmt.Sprintf("%v", req.GetLanguageCode()))
		}
		if req.GetPageSize() != 0 {
			params.Add("pageSize", fmt.Sprintf("%v", req.GetPageSize()))
		}
		if req.GetPageToken() != "" {
			params.Add("pageToken", fmt.Sprintf("%v", req.GetPageToken()))
		}
		params.Add("view", fmt.Sprintf("%v", req.GetView()))

		baseUrl.RawQuery = params.Encode()

		// Build HTTP headers from client and context metadata.
		hds := append(c.xGoogHeaders, "Content-Type", "application/json")
		headers := gax.BuildHeaders(ctx, hds...)
		e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
			if settings.Path != "" {
				baseUrl.Path = settings.Path
			}
			httpReq, err := http.NewRequest("GET", baseUrl.String(), nil)
			if err != nil {
				return err
			}
			httpReq.Header = headers

			httpRsp, err := c.httpClient.Do(httpReq)
			if err != nil {
				return err
			}
			defer httpRsp.Body.Close()

			if err = googleapi.CheckResponse(httpRsp); err != nil {
				return err
			}

			buf, err := io.ReadAll(httpRsp.Body)
			if err != nil {
				return err
			}

			if err := unm.Unmarshal(buf, resp); err != nil {
				return err
			}

			return nil
		}, opts...)
		if e != nil {
			return nil, "", e
		}
		it.Response = resp
		return resp.GetPhotos(), resp.GetNextPageToken(), nil
	}

	fetch := func(pageSize int, pageToken string) (string, error) {
		items, nextPageToken, err := it.InternalFetch(pageSize, pageToken)
		if err != nil {
			return "", err
		}
		it.items = append(it.items, items...)
		return nextPageToken, nil
	}

	it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf)
	it.pageInfo.MaxSize = int(req.GetPageSize())
	it.pageInfo.Token = req.GetPageToken()

	return it
}

// UpdatePhoto updates the metadata of a [Photo][google.streetview.publish.v1.Photo (at http://google.streetview.publish.v1.Photo)], such
// as pose, place association, connections, etc. Changing the pixels of a
// photo is not supported.
//
// Only the fields specified in the
// updateMask
// field are used. If updateMask is not present, the update applies to all
// fields.
//
// This method returns the following error codes:
//
//	google.rpc.Code.PERMISSION_DENIED if
//	the requesting user did not create the requested photo.
//
//	google.rpc.Code.INVALID_ARGUMENT if
//	the request is malformed.
//
//	google.rpc.Code.NOT_FOUND if the requested
//	photo does not exist.
//
//	google.rpc.Code.UNAVAILABLE if the
//	requested [Photo][google.streetview.publish.v1.Photo (at http://google.streetview.publish.v1.Photo)] is still being
//	indexed.
func (c *streetViewPublishRESTClient) UpdatePhoto(ctx context.Context, req *publishpb.UpdatePhotoRequest, opts ...gax.CallOption) (*publishpb.Photo, error) {
	m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true}
	body := req.GetPhoto()
	jsonReq, err := m.Marshal(body)
	if err != nil {
		return nil, err
	}

	baseUrl, err := url.Parse(c.endpoint)
	if err != nil {
		return nil, err
	}
	baseUrl.Path += fmt.Sprintf("/v1/photo/%v", req.GetPhoto().GetPhotoId().GetId())

	params := url.Values{}
	params.Add("$alt", "json;enum-encoding=int")
	if req.GetUpdateMask() != nil {
		updateMask, err := protojson.Marshal(req.GetUpdateMask())
		if err != nil {
			return nil, err
		}
		params.Add("updateMask", string(updateMask[1:len(updateMask)-1]))
	}

	baseUrl.RawQuery = params.Encode()

	// Build HTTP headers from client and context metadata.
	hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "photo.photo_id.id", url.QueryEscape(req.GetPhoto().GetPhotoId().GetId()))}

	hds = append(c.xGoogHeaders, hds...)
	hds = append(hds, "Content-Type", "application/json")
	headers := gax.BuildHeaders(ctx, hds...)
	opts = append((*c.CallOptions).UpdatePhoto[0:len((*c.CallOptions).UpdatePhoto):len((*c.CallOptions).UpdatePhoto)], opts...)
	unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true}
	resp := &publishpb.Photo{}
	e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		if settings.Path != "" {
			baseUrl.Path = settings.Path
		}
		httpReq, err := http.NewRequest("PUT", baseUrl.String(), bytes.NewReader(jsonReq))
		if err != nil {
			return err
		}
		httpReq = httpReq.WithContext(ctx)
		httpReq.Header = headers

		httpRsp, err := c.httpClient.Do(httpReq)
		if err != nil {
			return err
		}
		defer httpRsp.Body.Close()

		if err = googleapi.CheckResponse(httpRsp); err != nil {
			return err
		}

		buf, err := io.ReadAll(httpRsp.Body)
		if err != nil {
			return err
		}

		if err := unm.Unmarshal(buf, resp); err != nil {
			return err
		}

		return nil
	}, opts...)
	if e != nil {
		return nil, e
	}
	return resp, nil
}

// BatchUpdatePhotos updates the metadata of [Photos][google.streetview.publish.v1.Photo (at http://google.streetview.publish.v1.Photo)], such
// as pose, place association, connections, etc. Changing the pixels of photos
// is not supported.
//
// Note that if
// BatchUpdatePhotos
// fails, either critical fields are missing or there is an authentication
// error. Even if
// BatchUpdatePhotos
// succeeds, individual photos in the batch may have failures.
// These failures are specified in each
// PhotoResponse.status
// in
// BatchUpdatePhotosResponse.results.
// See
// UpdatePhoto
// for specific failures that can occur per photo.
//
// Only the fields specified in
// updateMask
// field are used. If updateMask is not present, the update applies to all
// fields.
//
// The number of
// UpdatePhotoRequest
// messages in a
// BatchUpdatePhotosRequest
// must not exceed 20.
//
// Note: To update
// Pose.altitude,
// Pose.latLngPair has to be
// filled as well. Otherwise, the request will fail.
func (c *streetViewPublishRESTClient) BatchUpdatePhotos(ctx context.Context, req *publishpb.BatchUpdatePhotosRequest, opts ...gax.CallOption) (*publishpb.BatchUpdatePhotosResponse, error) {
	m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true}
	jsonReq, err := m.Marshal(req)
	if err != nil {
		return nil, err
	}

	baseUrl, err := url.Parse(c.endpoint)
	if err != nil {
		return nil, err
	}
	baseUrl.Path += fmt.Sprintf("/v1/photos:batchUpdate")

	params := url.Values{}
	params.Add("$alt", "json;enum-encoding=int")

	baseUrl.RawQuery = params.Encode()

	// Build HTTP headers from client and context metadata.
	hds := append(c.xGoogHeaders, "Content-Type", "application/json")
	headers := gax.BuildHeaders(ctx, hds...)
	opts = append((*c.CallOptions).BatchUpdatePhotos[0:len((*c.CallOptions).BatchUpdatePhotos):len((*c.CallOptions).BatchUpdatePhotos)], opts...)
	unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true}
	resp := &publishpb.BatchUpdatePhotosResponse{}
	e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		if settings.Path != "" {
			baseUrl.Path = settings.Path
		}
		httpReq, err := http.NewRequest("POST", baseUrl.String(), bytes.NewReader(jsonReq))
		if err != nil {
			return err
		}
		httpReq = httpReq.WithContext(ctx)
		httpReq.Header = headers

		httpRsp, err := c.httpClient.Do(httpReq)
		if err != nil {
			return err
		}
		defer httpRsp.Body.Close()

		if err = googleapi.CheckResponse(httpRsp); err != nil {
			return err
		}

		buf, err := io.ReadAll(httpRsp.Body)
		if err != nil {
			return err
		}

		if err := unm.Unmarshal(buf, resp); err != nil {
			return err
		}

		return nil
	}, opts...)
	if e != nil {
		return nil, e
	}
	return resp, nil
}

// DeletePhoto deletes a [Photo][google.streetview.publish.v1.Photo (at http://google.streetview.publish.v1.Photo)] and its metadata.
//
// This method returns the following error codes:
//
//	google.rpc.Code.PERMISSION_DENIED if
//	the requesting user did not create the requested photo.
//
//	google.rpc.Code.NOT_FOUND if the photo ID
//	does not exist.
func (c *streetViewPublishRESTClient) DeletePhoto(ctx context.Context, req *publishpb.DeletePhotoRequest, opts ...gax.CallOption) error {
	baseUrl, err := url.Parse(c.endpoint)
	if err != nil {
		return err
	}
	baseUrl.Path += fmt.Sprintf("/v1/photo/%v", req.GetPhotoId())

	params := url.Values{}
	params.Add("$alt", "json;enum-encoding=int")

	baseUrl.RawQuery = params.Encode()

	// Build HTTP headers from client and context metadata.
	hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "photo_id", url.QueryEscape(req.GetPhotoId()))}

	hds = append(c.xGoogHeaders, hds...)
	hds = append(hds, "Content-Type", "application/json")
	headers := gax.BuildHeaders(ctx, hds...)
	return gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		if settings.Path != "" {
			baseUrl.Path = settings.Path
		}
		httpReq, err := http.NewRequest("DELETE", baseUrl.String(), nil)
		if err != nil {
			return err
		}
		httpReq = httpReq.WithContext(ctx)
		httpReq.Header = headers

		httpRsp, err := c.httpClient.Do(httpReq)
		if err != nil {
			return err
		}
		defer httpRsp.Body.Close()

		// Returns nil if there is no error, otherwise wraps
		// the response code and body into a non-nil error
		return googleapi.CheckResponse(httpRsp)
	}, opts...)
}

// BatchDeletePhotos deletes a list of [Photos][google.streetview.publish.v1.Photo (at http://google.streetview.publish.v1.Photo)] and their
// metadata.
//
// Note that if
// BatchDeletePhotos
// fails, either critical fields are missing or there is an authentication
// error. Even if
// BatchDeletePhotos
// succeeds, individual photos in the batch may have failures.
// These failures are specified in each
// PhotoResponse.status
// in
// BatchDeletePhotosResponse.results.
// See
// DeletePhoto
// for specific failures that can occur per photo.
func (c *streetViewPublishRESTClient) BatchDeletePhotos(ctx context.Context, req *publishpb.BatchDeletePhotosRequest, opts ...gax.CallOption) (*publishpb.BatchDeletePhotosResponse, error) {
	m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true}
	jsonReq, err := m.Marshal(req)
	if err != nil {
		return nil, err
	}

	baseUrl, err := url.Parse(c.endpoint)
	if err != nil {
		return nil, err
	}
	baseUrl.Path += fmt.Sprintf("/v1/photos:batchDelete")

	params := url.Values{}
	params.Add("$alt", "json;enum-encoding=int")

	baseUrl.RawQuery = params.Encode()

	// Build HTTP headers from client and context metadata.
	hds := append(c.xGoogHeaders, "Content-Type", "application/json")
	headers := gax.BuildHeaders(ctx, hds...)
	opts = append((*c.CallOptions).BatchDeletePhotos[0:len((*c.CallOptions).BatchDeletePhotos):len((*c.CallOptions).BatchDeletePhotos)], opts...)
	unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true}
	resp := &publishpb.BatchDeletePhotosResponse{}
	e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		if settings.Path != "" {
			baseUrl.Path = settings.Path
		}
		httpReq, err := http.NewRequest("POST", baseUrl.String(), bytes.NewReader(jsonReq))
		if err != nil {
			return err
		}
		httpReq = httpReq.WithContext(ctx)
		httpReq.Header = headers

		httpRsp, err := c.httpClient.Do(httpReq)
		if err != nil {
			return err
		}
		defer httpRsp.Body.Close()

		if err = googleapi.CheckResponse(httpRsp); err != nil {
			return err
		}

		buf, err := io.ReadAll(httpRsp.Body)
		if err != nil {
			return err
		}

		if err := unm.Unmarshal(buf, resp); err != nil {
			return err
		}

		return nil
	}, opts...)
	if e != nil {
		return nil, e
	}
	return resp, nil
}

// StartPhotoSequenceUpload creates an upload session to start uploading photo sequence data.
// The upload URL of the returned
// UploadRef is used to upload the
// data for the photoSequence.
//
// After the upload is complete, the
// UploadRef is used with
// CreatePhotoSequence
// to create the PhotoSequence
// object entry.
func (c *streetViewPublishRESTClient) StartPhotoSequenceUpload(ctx context.Context, req *emptypb.Empty, opts ...gax.CallOption) (*publishpb.UploadRef, error) {
	m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true}
	jsonReq, err := m.Marshal(req)
	if err != nil {
		return nil, err
	}

	baseUrl, err := url.Parse(c.endpoint)
	if err != nil {
		return nil, err
	}
	baseUrl.Path += fmt.Sprintf("/v1/photoSequence:startUpload")

	params := url.Values{}
	params.Add("$alt", "json;enum-encoding=int")

	baseUrl.RawQuery = params.Encode()

	// Build HTTP headers from client and context metadata.
	hds := append(c.xGoogHeaders, "Content-Type", "application/json")
	headers := gax.BuildHeaders(ctx, hds...)
	opts = append((*c.CallOptions).StartPhotoSequenceUpload[0:len((*c.CallOptions).StartPhotoSequenceUpload):len((*c.CallOptions).StartPhotoSequenceUpload)], opts...)
	unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true}
	resp := &publishpb.UploadRef{}
	e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		if settings.Path != "" {
			baseUrl.Path = settings.Path
		}
		httpReq, err := http.NewRequest("POST", baseUrl.String(), bytes.NewReader(jsonReq))
		if err != nil {
			return err
		}
		httpReq = httpReq.WithContext(ctx)
		httpReq.Header = headers

		httpRsp, err := c.httpClient.Do(httpReq)
		if err != nil {
			return err
		}
		defer httpRsp.Body.Close()

		if err = googleapi.CheckResponse(httpRsp); err != nil {
			return err
		}

		buf, err := io.ReadAll(httpRsp.Body)
		if err != nil {
			return err
		}

		if err := unm.Unmarshal(buf, resp); err != nil {
			return err
		}

		return nil
	}, opts...)
	if e != nil {
		return nil, e
	}
	return resp, nil
}

// CreatePhotoSequence after the client finishes uploading the
// PhotoSequence with the
// returned UploadRef,
// CreatePhotoSequence
// extracts a sequence of 360 photos from a video or Extensible Device
// Metadata (XDM, http://www.xdm.org/ (at http://www.xdm.org/)) to be published to Street View on
// Google Maps.
//
// CreatePhotoSequence returns an Operation,
// with the PhotoSequence Id set
// in the Operation.name field.
//
// This method returns the following error codes:
//
//	google.rpc.Code.INVALID_ARGUMENT if
//	the request is malformed.
//
//	google.rpc.Code.NOT_FOUND if the upload
//	reference does not exist.
func (c *streetViewPublishRESTClient) CreatePhotoSequence(ctx context.Context, req *publishpb.CreatePhotoSequenceRequest, opts ...gax.CallOption) (*CreatePhotoSequenceOperation, error) {
	m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true}
	body := req.GetPhotoSequence()
	jsonReq, err := m.Marshal(body)
	if err != nil {
		return nil, err
	}

	baseUrl, err := url.Parse(c.endpoint)
	if err != nil {
		return nil, err
	}
	baseUrl.Path += fmt.Sprintf("/v1/photoSequence")

	params := url.Values{}
	params.Add("$alt", "json;enum-encoding=int")
	params.Add("inputType", fmt.Sprintf("%v", req.GetInputType()))

	baseUrl.RawQuery = params.Encode()

	// Build HTTP headers from client and context metadata.
	hds := append(c.xGoogHeaders, "Content-Type", "application/json")
	headers := gax.BuildHeaders(ctx, hds...)
	unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true}
	resp := &longrunningpb.Operation{}
	e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		if settings.Path != "" {
			baseUrl.Path = settings.Path
		}
		httpReq, err := http.NewRequest("POST", baseUrl.String(), bytes.NewReader(jsonReq))
		if err != nil {
			return err
		}
		httpReq = httpReq.WithContext(ctx)
		httpReq.Header = headers

		httpRsp, err := c.httpClient.Do(httpReq)
		if err != nil {
			return err
		}
		defer httpRsp.Body.Close()

		if err = googleapi.CheckResponse(httpRsp); err != nil {
			return err
		}

		buf, err := io.ReadAll(httpRsp.Body)
		if err != nil {
			return err
		}

		if err := unm.Unmarshal(buf, resp); err != nil {
			return err
		}

		return nil
	}, opts...)
	if e != nil {
		return nil, e
	}

	override := fmt.Sprintf("/v1/%s", resp.GetName())
	return &CreatePhotoSequenceOperation{
		lro:      longrunning.InternalNewOperation(*c.LROClient, resp),
		pollPath: override,
	}, nil
}

// GetPhotoSequence gets the metadata of the specified
// PhotoSequence via the
// Operation interface.
//
// This method returns the following three types of responses:
//
//	Operation.done = false, if the processing of
//	PhotoSequence is not
//	finished yet.
//
//	Operation.done = true and Operation.error is populated, if there was
//	an error in processing.
//
//	Operation.done = true and Operation.response is poulated, which
//	contains a PhotoSequence
//	message.
//
// This method returns the following error codes:
//
//	google.rpc.Code.PERMISSION_DENIED if
//	the requesting user did not create the requested
//	PhotoSequence.
//
//	google.rpc.Code.NOT_FOUND if the requested
//	PhotoSequence does not exist.
func (c *streetViewPublishRESTClient) GetPhotoSequence(ctx context.Context, req *publishpb.GetPhotoSequenceRequest, opts ...gax.CallOption) (*GetPhotoSequenceOperation, error) {
	baseUrl, err := url.Parse(c.endpoint)
	if err != nil {
		return nil, err
	}
	baseUrl.Path += fmt.Sprintf("/v1/photoSequence/%v", req.GetSequenceId())

	params := url.Values{}
	params.Add("$alt", "json;enum-encoding=int")
	if req.GetFilter() != "" {
		params.Add("filter", fmt.Sprintf("%v", req.GetFilter()))
	}
	if req.GetView() != 0 {
		params.Add("view", fmt.Sprintf("%v", req.GetView()))
	}

	baseUrl.RawQuery = params.Encode()

	// Build HTTP headers from client and context metadata.
	hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "sequence_id", url.QueryEscape(req.GetSequenceId()))}

	hds = append(c.xGoogHeaders, hds...)
	hds = append(hds, "Content-Type", "application/json")
	headers := gax.BuildHeaders(ctx, hds...)
	unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true}
	resp := &longrunningpb.Operation{}
	e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		if settings.Path != "" {
			baseUrl.Path = settings.Path
		}
		httpReq, err := http.NewRequest("GET", baseUrl.String(), nil)
		if err != nil {
			return err
		}
		httpReq = httpReq.WithContext(ctx)
		httpReq.Header = headers

		httpRsp, err := c.httpClient.Do(httpReq)
		if err != nil {
			return err
		}
		defer httpRsp.Body.Close()

		if err = googleapi.CheckResponse(httpRsp); err != nil {
			return err
		}

		buf, err := io.ReadAll(httpRsp.Body)
		if err != nil {
			return err
		}

		if err := unm.Unmarshal(buf, resp); err != nil {
			return err
		}

		return nil
	}, opts...)
	if e != nil {
		return nil, e
	}

	override := fmt.Sprintf("/v1/%s", resp.GetName())
	return &GetPhotoSequenceOperation{
		lro:      longrunning.InternalNewOperation(*c.LROClient, resp),
		pollPath: override,
	}, nil
}

// ListPhotoSequences lists all the PhotoSequences
// that belong to the user, in descending CreatePhotoSequence timestamp order.
func (c *streetViewPublishRESTClient) ListPhotoSequences(ctx context.Context, req *publishpb.ListPhotoSequencesRequest, opts ...gax.CallOption) *OperationIterator {
	it := &OperationIterator{}
	req = proto.Clone(req).(*publishpb.ListPhotoSequencesRequest)
	unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true}
	it.InternalFetch = func(pageSize int, pageToken string) ([]*longrunningpb.Operation, string, error) {
		resp := &publishpb.ListPhotoSequencesResponse{}
		if pageToken != "" {
			req.PageToken = pageToken
		}
		if pageSize > math.MaxInt32 {
			req.PageSize = math.MaxInt32
		} else if pageSize != 0 {
			req.PageSize = int32(pageSize)
		}
		baseUrl, err := url.Parse(c.endpoint)
		if err != nil {
			return nil, "", err
		}
		baseUrl.Path += fmt.Sprintf("/v1/photoSequences")

		params := url.Values{}
		params.Add("$alt", "json;enum-encoding=int")
		if req.GetFilter() != "" {
			params.Add("filter", fmt.Sprintf("%v", req.GetFilter()))
		}
		if req.GetPageSize() != 0 {
			params.Add("pageSize", fmt.Sprintf("%v", req.GetPageSize()))
		}
		if req.GetPageToken() != "" {
			params.Add("pageToken", fmt.Sprintf("%v", req.GetPageToken()))
		}

		baseUrl.RawQuery = params.Encode()

		// Build HTTP headers from client and context metadata.
		hds := append(c.xGoogHeaders, "Content-Type", "application/json")
		headers := gax.BuildHeaders(ctx, hds...)
		e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
			if settings.Path != "" {
				baseUrl.Path = settings.Path
			}
			httpReq, err := http.NewRequest("GET", baseUrl.String(), nil)
			if err != nil {
				return err
			}
			httpReq.Header = headers

			httpRsp, err := c.httpClient.Do(httpReq)
			if err != nil {
				return err
			}
			defer httpRsp.Body.Close()

			if err = googleapi.CheckResponse(httpRsp); err != nil {
				return err
			}

			buf, err := io.ReadAll(httpRsp.Body)
			if err != nil {
				return err
			}

			if err := unm.Unmarshal(buf, resp); err != nil {
				return err
			}

			return nil
		}, opts...)
		if e != nil {
			return nil, "", e
		}
		it.Response = resp
		return resp.GetPhotoSequences(), resp.GetNextPageToken(), nil
	}

	fetch := func(pageSize int, pageToken string) (string, error) {
		items, nextPageToken, err := it.InternalFetch(pageSize, pageToken)
		if err != nil {
			return "", err
		}
		it.items = append(it.items, items...)
		return nextPageToken, nil
	}

	it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf)
	it.pageInfo.MaxSize = int(req.GetPageSize())
	it.pageInfo.Token = req.GetPageToken()

	return it
}

// DeletePhotoSequence deletes a PhotoSequence and
// its metadata.
//
// This method returns the following error codes:
//
//	google.rpc.Code.PERMISSION_DENIED if
//	the requesting user did not create the requested photo sequence.
//
//	google.rpc.Code.NOT_FOUND if the photo
//	sequence ID does not exist.
//
//	google.rpc.Code.FAILED_PRECONDITION if the photo sequence ID is not
//	yet finished processing.
func (c *streetViewPublishRESTClient) DeletePhotoSequence(ctx context.Context, req *publishpb.DeletePhotoSequenceRequest, opts ...gax.CallOption) error {
	baseUrl, err := url.Parse(c.endpoint)
	if err != nil {
		return err
	}
	baseUrl.Path += fmt.Sprintf("/v1/photoSequence/%v", req.GetSequenceId())

	params := url.Values{}
	params.Add("$alt", "json;enum-encoding=int")

	baseUrl.RawQuery = params.Encode()

	// Build HTTP headers from client and context metadata.
	hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "sequence_id", url.QueryEscape(req.GetSequenceId()))}

	hds = append(c.xGoogHeaders, hds...)
	hds = append(hds, "Content-Type", "application/json")
	headers := gax.BuildHeaders(ctx, hds...)
	return gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		if settings.Path != "" {
			baseUrl.Path = settings.Path
		}
		httpReq, err := http.NewRequest("DELETE", baseUrl.String(), nil)
		if err != nil {
			return err
		}
		httpReq = httpReq.WithContext(ctx)
		httpReq.Header = headers

		httpRsp, err := c.httpClient.Do(httpReq)
		if err != nil {
			return err
		}
		defer httpRsp.Body.Close()

		// Returns nil if there is no error, otherwise wraps
		// the response code and body into a non-nil error
		return googleapi.CheckResponse(httpRsp)
	}, opts...)
}

// CreatePhotoSequenceOperation returns a new CreatePhotoSequenceOperation from a given name.
// The name must be that of a previously created CreatePhotoSequenceOperation, possibly from a different process.
func (c *streetViewPublishGRPCClient) CreatePhotoSequenceOperation(name string) *CreatePhotoSequenceOperation {
	return &CreatePhotoSequenceOperation{
		lro: longrunning.InternalNewOperation(*c.LROClient, &longrunningpb.Operation{Name: name}),
	}
}

// CreatePhotoSequenceOperation returns a new CreatePhotoSequenceOperation from a given name.
// The name must be that of a previously created CreatePhotoSequenceOperation, possibly from a different process.
func (c *streetViewPublishRESTClient) CreatePhotoSequenceOperation(name string) *CreatePhotoSequenceOperation {
	override := fmt.Sprintf("/v1/%s", name)
	return &CreatePhotoSequenceOperation{
		lro:      longrunning.InternalNewOperation(*c.LROClient, &longrunningpb.Operation{Name: name}),
		pollPath: override,
	}
}

// GetPhotoSequenceOperation returns a new GetPhotoSequenceOperation from a given name.
// The name must be that of a previously created GetPhotoSequenceOperation, possibly from a different process.
func (c *streetViewPublishGRPCClient) GetPhotoSequenceOperation(name string) *GetPhotoSequenceOperation {
	return &GetPhotoSequenceOperation{
		lro: longrunning.InternalNewOperation(*c.LROClient, &longrunningpb.Operation{Name: name}),
	}
}

// GetPhotoSequenceOperation returns a new GetPhotoSequenceOperation from a given name.
// The name must be that of a previously created GetPhotoSequenceOperation, possibly from a different process.
func (c *streetViewPublishRESTClient) GetPhotoSequenceOperation(name string) *GetPhotoSequenceOperation {
	override := fmt.Sprintf("/v1/%s", name)
	return &GetPhotoSequenceOperation{
		lro:      longrunning.InternalNewOperation(*c.LROClient, &longrunningpb.Operation{Name: name}),
		pollPath: override,
	}
}
