// 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 shell

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"
	shellpb "cloud.google.com/go/shell/apiv1/shellpb"
	gax "github.com/googleapis/gax-go/v2"
	"google.golang.org/api/googleapi"
	"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"
)

var newCloudShellClientHook clientHook

// CloudShellCallOptions contains the retry settings for each method of CloudShellClient.
type CloudShellCallOptions struct {
	GetEnvironment       []gax.CallOption
	StartEnvironment     []gax.CallOption
	AuthorizeEnvironment []gax.CallOption
	AddPublicKey         []gax.CallOption
	RemovePublicKey      []gax.CallOption
}

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

func defaultCloudShellCallOptions() *CloudShellCallOptions {
	return &CloudShellCallOptions{
		GetEnvironment: []gax.CallOption{
			gax.WithTimeout(60000 * time.Millisecond),
			gax.WithRetry(func() gax.Retryer {
				return gax.OnCodes([]codes.Code{
					codes.Unavailable,
					codes.Unknown,
				}, gax.Backoff{
					Initial:    1000 * time.Millisecond,
					Max:        60000 * time.Millisecond,
					Multiplier: 1.30,
				})
			}),
		},
		StartEnvironment: []gax.CallOption{
			gax.WithTimeout(60000 * time.Millisecond),
		},
		AuthorizeEnvironment: []gax.CallOption{
			gax.WithTimeout(60000 * time.Millisecond),
		},
		AddPublicKey: []gax.CallOption{
			gax.WithTimeout(60000 * time.Millisecond),
		},
		RemovePublicKey: []gax.CallOption{
			gax.WithTimeout(60000 * time.Millisecond),
		},
	}
}

func defaultCloudShellRESTCallOptions() *CloudShellCallOptions {
	return &CloudShellCallOptions{
		GetEnvironment: []gax.CallOption{
			gax.WithTimeout(60000 * time.Millisecond),
			gax.WithRetry(func() gax.Retryer {
				return gax.OnHTTPCodes(gax.Backoff{
					Initial:    1000 * time.Millisecond,
					Max:        60000 * time.Millisecond,
					Multiplier: 1.30,
				},
					http.StatusServiceUnavailable,
					http.StatusInternalServerError)
			}),
		},
		StartEnvironment: []gax.CallOption{
			gax.WithTimeout(60000 * time.Millisecond),
		},
		AuthorizeEnvironment: []gax.CallOption{
			gax.WithTimeout(60000 * time.Millisecond),
		},
		AddPublicKey: []gax.CallOption{
			gax.WithTimeout(60000 * time.Millisecond),
		},
		RemovePublicKey: []gax.CallOption{
			gax.WithTimeout(60000 * time.Millisecond),
		},
	}
}

// internalCloudShellClient is an interface that defines the methods available from Cloud Shell API.
type internalCloudShellClient interface {
	Close() error
	setGoogleClientInfo(...string)
	Connection() *grpc.ClientConn
	GetEnvironment(context.Context, *shellpb.GetEnvironmentRequest, ...gax.CallOption) (*shellpb.Environment, error)
	StartEnvironment(context.Context, *shellpb.StartEnvironmentRequest, ...gax.CallOption) (*StartEnvironmentOperation, error)
	StartEnvironmentOperation(name string) *StartEnvironmentOperation
	AuthorizeEnvironment(context.Context, *shellpb.AuthorizeEnvironmentRequest, ...gax.CallOption) (*AuthorizeEnvironmentOperation, error)
	AuthorizeEnvironmentOperation(name string) *AuthorizeEnvironmentOperation
	AddPublicKey(context.Context, *shellpb.AddPublicKeyRequest, ...gax.CallOption) (*AddPublicKeyOperation, error)
	AddPublicKeyOperation(name string) *AddPublicKeyOperation
	RemovePublicKey(context.Context, *shellpb.RemovePublicKeyRequest, ...gax.CallOption) (*RemovePublicKeyOperation, error)
	RemovePublicKeyOperation(name string) *RemovePublicKeyOperation
}

// CloudShellClient is a client for interacting with Cloud Shell API.
// Methods, except Close, may be called concurrently. However, fields must not be modified concurrently with method calls.
//
// API for interacting with Google Cloud Shell. Each user of Cloud Shell has at
// least one environment, which has the ID “default”. Environment consists of a
// Docker image defining what is installed on the environment and a home
// directory containing the user’s data that will remain across sessions.
// Clients use this API to start and fetch information about their environment,
// which can then be used to connect to that environment via a separate SSH
// client.
type CloudShellClient struct {
	// The internal transport-dependent client.
	internalClient internalCloudShellClient

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

	// 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 *CloudShellClient) 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 *CloudShellClient) 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 *CloudShellClient) Connection() *grpc.ClientConn {
	return c.internalClient.Connection()
}

// GetEnvironment gets an environment. Returns NOT_FOUND if the environment does not exist.
func (c *CloudShellClient) GetEnvironment(ctx context.Context, req *shellpb.GetEnvironmentRequest, opts ...gax.CallOption) (*shellpb.Environment, error) {
	return c.internalClient.GetEnvironment(ctx, req, opts...)
}

// StartEnvironment starts an existing environment, allowing clients to connect to it. The
// returned operation will contain an instance of StartEnvironmentMetadata in
// its metadata field. Users can wait for the environment to start by polling
// this operation via GetOperation. Once the environment has finished starting
// and is ready to accept connections, the operation will contain a
// StartEnvironmentResponse in its response field.
func (c *CloudShellClient) StartEnvironment(ctx context.Context, req *shellpb.StartEnvironmentRequest, opts ...gax.CallOption) (*StartEnvironmentOperation, error) {
	return c.internalClient.StartEnvironment(ctx, req, opts...)
}

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

// AuthorizeEnvironment sends OAuth credentials to a running environment on behalf of a user. When
// this completes, the environment will be authorized to run various Google
// Cloud command line tools without requiring the user to manually
// authenticate.
func (c *CloudShellClient) AuthorizeEnvironment(ctx context.Context, req *shellpb.AuthorizeEnvironmentRequest, opts ...gax.CallOption) (*AuthorizeEnvironmentOperation, error) {
	return c.internalClient.AuthorizeEnvironment(ctx, req, opts...)
}

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

// AddPublicKey adds a public SSH key to an environment, allowing clients with the
// corresponding private key to connect to that environment via SSH. If a key
// with the same content already exists, this will error with ALREADY_EXISTS.
func (c *CloudShellClient) AddPublicKey(ctx context.Context, req *shellpb.AddPublicKeyRequest, opts ...gax.CallOption) (*AddPublicKeyOperation, error) {
	return c.internalClient.AddPublicKey(ctx, req, opts...)
}

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

// RemovePublicKey removes a public SSH key from an environment. Clients will no longer be
// able to connect to the environment using the corresponding private key.
// If a key with the same content is not present, this will error with
// NOT_FOUND.
func (c *CloudShellClient) RemovePublicKey(ctx context.Context, req *shellpb.RemovePublicKeyRequest, opts ...gax.CallOption) (*RemovePublicKeyOperation, error) {
	return c.internalClient.RemovePublicKey(ctx, req, opts...)
}

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

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

	// Points back to the CallOptions field of the containing CloudShellClient
	CallOptions **CloudShellCallOptions

	// The gRPC API client.
	cloudShellClient shellpb.CloudShellServiceClient

	// 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
}

// NewCloudShellClient creates a new cloud shell service client based on gRPC.
// The returned client must be Closed when it is done being used to clean up its underlying connections.
//
// API for interacting with Google Cloud Shell. Each user of Cloud Shell has at
// least one environment, which has the ID “default”. Environment consists of a
// Docker image defining what is installed on the environment and a home
// directory containing the user’s data that will remain across sessions.
// Clients use this API to start and fetch information about their environment,
// which can then be used to connect to that environment via a separate SSH
// client.
func NewCloudShellClient(ctx context.Context, opts ...option.ClientOption) (*CloudShellClient, error) {
	clientOpts := defaultCloudShellGRPCClientOptions()
	if newCloudShellClientHook != nil {
		hookOpts, err := newCloudShellClientHook(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 := CloudShellClient{CallOptions: defaultCloudShellCallOptions()}

	c := &cloudShellGRPCClient{
		connPool:         connPool,
		cloudShellClient: shellpb.NewCloudShellServiceClient(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 *cloudShellGRPCClient) 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 *cloudShellGRPCClient) 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 *cloudShellGRPCClient) Close() error {
	return c.connPool.Close()
}

// Methods, except Close, may be called concurrently. However, fields must not be modified concurrently with method calls.
type cloudShellRESTClient 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 CloudShellClient
	CallOptions **CloudShellCallOptions
}

// NewCloudShellRESTClient creates a new cloud shell service rest client.
//
// API for interacting with Google Cloud Shell. Each user of Cloud Shell has at
// least one environment, which has the ID “default”. Environment consists of a
// Docker image defining what is installed on the environment and a home
// directory containing the user’s data that will remain across sessions.
// Clients use this API to start and fetch information about their environment,
// which can then be used to connect to that environment via a separate SSH
// client.
func NewCloudShellRESTClient(ctx context.Context, opts ...option.ClientOption) (*CloudShellClient, error) {
	clientOpts := append(defaultCloudShellRESTClientOptions(), opts...)
	httpClient, endpoint, err := httptransport.NewClient(ctx, clientOpts...)
	if err != nil {
		return nil, err
	}

	callOpts := defaultCloudShellRESTCallOptions()
	c := &cloudShellRESTClient{
		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 &CloudShellClient{internalClient: c, CallOptions: callOpts}, nil
}

func defaultCloudShellRESTClientOptions() []option.ClientOption {
	return []option.ClientOption{
		internaloption.WithDefaultEndpoint("https://cloudshell.googleapis.com"),
		internaloption.WithDefaultEndpointTemplate("https://cloudshell.UNIVERSE_DOMAIN"),
		internaloption.WithDefaultMTLSEndpoint("https://cloudshell.mtls.googleapis.com"),
		internaloption.WithDefaultUniverseDomain("googleapis.com"),
		internaloption.WithDefaultAudience("https://cloudshell.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 *cloudShellRESTClient) 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 *cloudShellRESTClient) 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 *cloudShellRESTClient) Connection() *grpc.ClientConn {
	return nil
}
func (c *cloudShellGRPCClient) GetEnvironment(ctx context.Context, req *shellpb.GetEnvironmentRequest, opts ...gax.CallOption) (*shellpb.Environment, error) {
	hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))}

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

func (c *cloudShellGRPCClient) StartEnvironment(ctx context.Context, req *shellpb.StartEnvironmentRequest, opts ...gax.CallOption) (*StartEnvironmentOperation, error) {
	hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))}

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

func (c *cloudShellGRPCClient) AuthorizeEnvironment(ctx context.Context, req *shellpb.AuthorizeEnvironmentRequest, opts ...gax.CallOption) (*AuthorizeEnvironmentOperation, error) {
	hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))}

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

func (c *cloudShellGRPCClient) AddPublicKey(ctx context.Context, req *shellpb.AddPublicKeyRequest, opts ...gax.CallOption) (*AddPublicKeyOperation, error) {
	hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "environment", url.QueryEscape(req.GetEnvironment()))}

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

func (c *cloudShellGRPCClient) RemovePublicKey(ctx context.Context, req *shellpb.RemovePublicKeyRequest, opts ...gax.CallOption) (*RemovePublicKeyOperation, error) {
	hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "environment", url.QueryEscape(req.GetEnvironment()))}

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

// GetEnvironment gets an environment. Returns NOT_FOUND if the environment does not exist.
func (c *cloudShellRESTClient) GetEnvironment(ctx context.Context, req *shellpb.GetEnvironmentRequest, opts ...gax.CallOption) (*shellpb.Environment, error) {
	baseUrl, err := url.Parse(c.endpoint)
	if err != nil {
		return nil, err
	}
	baseUrl.Path += fmt.Sprintf("/v1/%v", req.GetName())

	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", "name", url.QueryEscape(req.GetName()))}

	hds = append(c.xGoogHeaders, hds...)
	hds = append(hds, "Content-Type", "application/json")
	headers := gax.BuildHeaders(ctx, hds...)
	opts = append((*c.CallOptions).GetEnvironment[0:len((*c.CallOptions).GetEnvironment):len((*c.CallOptions).GetEnvironment)], opts...)
	unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true}
	resp := &shellpb.Environment{}
	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
}

// StartEnvironment starts an existing environment, allowing clients to connect to it. The
// returned operation will contain an instance of StartEnvironmentMetadata in
// its metadata field. Users can wait for the environment to start by polling
// this operation via GetOperation. Once the environment has finished starting
// and is ready to accept connections, the operation will contain a
// StartEnvironmentResponse in its response field.
func (c *cloudShellRESTClient) StartEnvironment(ctx context.Context, req *shellpb.StartEnvironmentRequest, opts ...gax.CallOption) (*StartEnvironmentOperation, 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/%v:start", req.GetName())

	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", "name", url.QueryEscape(req.GetName()))}

	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("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 &StartEnvironmentOperation{
		lro:      longrunning.InternalNewOperation(*c.LROClient, resp),
		pollPath: override,
	}, nil
}

// AuthorizeEnvironment sends OAuth credentials to a running environment on behalf of a user. When
// this completes, the environment will be authorized to run various Google
// Cloud command line tools without requiring the user to manually
// authenticate.
func (c *cloudShellRESTClient) AuthorizeEnvironment(ctx context.Context, req *shellpb.AuthorizeEnvironmentRequest, opts ...gax.CallOption) (*AuthorizeEnvironmentOperation, 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/%v:authorize", req.GetName())

	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", "name", url.QueryEscape(req.GetName()))}

	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("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 &AuthorizeEnvironmentOperation{
		lro:      longrunning.InternalNewOperation(*c.LROClient, resp),
		pollPath: override,
	}, nil
}

// AddPublicKey adds a public SSH key to an environment, allowing clients with the
// corresponding private key to connect to that environment via SSH. If a key
// with the same content already exists, this will error with ALREADY_EXISTS.
func (c *cloudShellRESTClient) AddPublicKey(ctx context.Context, req *shellpb.AddPublicKeyRequest, opts ...gax.CallOption) (*AddPublicKeyOperation, 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/%v:addPublicKey", req.GetEnvironment())

	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", "environment", url.QueryEscape(req.GetEnvironment()))}

	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("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 &AddPublicKeyOperation{
		lro:      longrunning.InternalNewOperation(*c.LROClient, resp),
		pollPath: override,
	}, nil
}

// RemovePublicKey removes a public SSH key from an environment. Clients will no longer be
// able to connect to the environment using the corresponding private key.
// If a key with the same content is not present, this will error with
// NOT_FOUND.
func (c *cloudShellRESTClient) RemovePublicKey(ctx context.Context, req *shellpb.RemovePublicKeyRequest, opts ...gax.CallOption) (*RemovePublicKeyOperation, 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/%v:removePublicKey", req.GetEnvironment())

	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", "environment", url.QueryEscape(req.GetEnvironment()))}

	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("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 &RemovePublicKeyOperation{
		lro:      longrunning.InternalNewOperation(*c.LROClient, resp),
		pollPath: override,
	}, nil
}

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

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

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

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

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

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

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

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