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

import (
	"context"
	"fmt"
	"math"
	"net/url"
	"regexp"
	"strings"
	"time"

	"cloud.google.com/go/longrunning"
	lroauto "cloud.google.com/go/longrunning/autogen"
	longrunningpb "cloud.google.com/go/longrunning/autogen/longrunningpb"
	controlpb "cloud.google.com/go/storage/control/apiv2/controlpb"
	"github.com/google/uuid"
	gax "github.com/googleapis/gax-go/v2"
	"google.golang.org/api/iterator"
	"google.golang.org/api/option"
	"google.golang.org/api/option/internaloption"
	gtransport "google.golang.org/api/transport/grpc"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/protobuf/proto"
)

var newStorageControlClientHook clientHook

// StorageControlCallOptions contains the retry settings for each method of StorageControlClient.
type StorageControlCallOptions struct {
	CreateFolder        []gax.CallOption
	DeleteFolder        []gax.CallOption
	GetFolder           []gax.CallOption
	ListFolders         []gax.CallOption
	RenameFolder        []gax.CallOption
	GetStorageLayout    []gax.CallOption
	CreateManagedFolder []gax.CallOption
	DeleteManagedFolder []gax.CallOption
	GetManagedFolder    []gax.CallOption
	ListManagedFolders  []gax.CallOption
}

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

func defaultStorageControlCallOptions() *StorageControlCallOptions {
	return &StorageControlCallOptions{
		CreateFolder: []gax.CallOption{
			gax.WithTimeout(60000 * time.Millisecond),
		},
		DeleteFolder: []gax.CallOption{
			gax.WithTimeout(60000 * time.Millisecond),
		},
		GetFolder: []gax.CallOption{
			gax.WithTimeout(60000 * time.Millisecond),
			gax.WithRetry(func() gax.Retryer {
				return gax.OnCodes([]codes.Code{
					codes.ResourceExhausted,
					codes.Unavailable,
					codes.DeadlineExceeded,
					codes.Internal,
					codes.Unknown,
				}, gax.Backoff{
					Initial:    1000 * time.Millisecond,
					Max:        60000 * time.Millisecond,
					Multiplier: 2.00,
				})
			}),
		},
		ListFolders: []gax.CallOption{
			gax.WithTimeout(60000 * time.Millisecond),
			gax.WithRetry(func() gax.Retryer {
				return gax.OnCodes([]codes.Code{
					codes.ResourceExhausted,
					codes.Unavailable,
					codes.DeadlineExceeded,
					codes.Internal,
					codes.Unknown,
				}, gax.Backoff{
					Initial:    1000 * time.Millisecond,
					Max:        60000 * time.Millisecond,
					Multiplier: 2.00,
				})
			}),
		},
		RenameFolder: []gax.CallOption{
			gax.WithTimeout(60000 * time.Millisecond),
			gax.WithRetry(func() gax.Retryer {
				return gax.OnCodes([]codes.Code{
					codes.ResourceExhausted,
					codes.Unavailable,
					codes.DeadlineExceeded,
					codes.Internal,
					codes.Unknown,
				}, gax.Backoff{
					Initial:    1000 * time.Millisecond,
					Max:        60000 * time.Millisecond,
					Multiplier: 2.00,
				})
			}),
		},
		GetStorageLayout: []gax.CallOption{
			gax.WithTimeout(60000 * time.Millisecond),
			gax.WithRetry(func() gax.Retryer {
				return gax.OnCodes([]codes.Code{
					codes.ResourceExhausted,
					codes.Unavailable,
					codes.DeadlineExceeded,
					codes.Internal,
					codes.Unknown,
				}, gax.Backoff{
					Initial:    1000 * time.Millisecond,
					Max:        60000 * time.Millisecond,
					Multiplier: 2.00,
				})
			}),
		},
		CreateManagedFolder: []gax.CallOption{
			gax.WithTimeout(60000 * time.Millisecond),
		},
		DeleteManagedFolder: []gax.CallOption{
			gax.WithTimeout(60000 * time.Millisecond),
		},
		GetManagedFolder: []gax.CallOption{
			gax.WithTimeout(60000 * time.Millisecond),
			gax.WithRetry(func() gax.Retryer {
				return gax.OnCodes([]codes.Code{
					codes.ResourceExhausted,
					codes.Unavailable,
					codes.DeadlineExceeded,
					codes.Internal,
					codes.Unknown,
				}, gax.Backoff{
					Initial:    1000 * time.Millisecond,
					Max:        60000 * time.Millisecond,
					Multiplier: 2.00,
				})
			}),
		},
		ListManagedFolders: []gax.CallOption{
			gax.WithTimeout(60000 * time.Millisecond),
			gax.WithRetry(func() gax.Retryer {
				return gax.OnCodes([]codes.Code{
					codes.ResourceExhausted,
					codes.Unavailable,
					codes.DeadlineExceeded,
					codes.Internal,
					codes.Unknown,
				}, gax.Backoff{
					Initial:    1000 * time.Millisecond,
					Max:        60000 * time.Millisecond,
					Multiplier: 2.00,
				})
			}),
		},
	}
}

// internalStorageControlClient is an interface that defines the methods available from Storage Control API.
type internalStorageControlClient interface {
	Close() error
	setGoogleClientInfo(...string)
	Connection() *grpc.ClientConn
	CreateFolder(context.Context, *controlpb.CreateFolderRequest, ...gax.CallOption) (*controlpb.Folder, error)
	DeleteFolder(context.Context, *controlpb.DeleteFolderRequest, ...gax.CallOption) error
	GetFolder(context.Context, *controlpb.GetFolderRequest, ...gax.CallOption) (*controlpb.Folder, error)
	ListFolders(context.Context, *controlpb.ListFoldersRequest, ...gax.CallOption) *FolderIterator
	RenameFolder(context.Context, *controlpb.RenameFolderRequest, ...gax.CallOption) (*RenameFolderOperation, error)
	RenameFolderOperation(name string) *RenameFolderOperation
	GetStorageLayout(context.Context, *controlpb.GetStorageLayoutRequest, ...gax.CallOption) (*controlpb.StorageLayout, error)
	CreateManagedFolder(context.Context, *controlpb.CreateManagedFolderRequest, ...gax.CallOption) (*controlpb.ManagedFolder, error)
	DeleteManagedFolder(context.Context, *controlpb.DeleteManagedFolderRequest, ...gax.CallOption) error
	GetManagedFolder(context.Context, *controlpb.GetManagedFolderRequest, ...gax.CallOption) (*controlpb.ManagedFolder, error)
	ListManagedFolders(context.Context, *controlpb.ListManagedFoldersRequest, ...gax.CallOption) *ManagedFolderIterator
}

// StorageControlClient is a client for interacting with Storage Control API.
// Methods, except Close, may be called concurrently. However, fields must not be modified concurrently with method calls.
//
// StorageControl service includes selected control plane operations.
type StorageControlClient struct {
	// The internal transport-dependent client.
	internalClient internalStorageControlClient

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

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

// CreateFolder creates a new folder. This operation is only applicable to a hierarchical
// namespace enabled bucket.
// Hierarchical namespace buckets are in allowlist preview.
func (c *StorageControlClient) CreateFolder(ctx context.Context, req *controlpb.CreateFolderRequest, opts ...gax.CallOption) (*controlpb.Folder, error) {
	return c.internalClient.CreateFolder(ctx, req, opts...)
}

// DeleteFolder permanently deletes an empty folder. This operation is only applicable to a
// hierarchical namespace enabled bucket.
// Hierarchical namespace buckets are in allowlist preview.
func (c *StorageControlClient) DeleteFolder(ctx context.Context, req *controlpb.DeleteFolderRequest, opts ...gax.CallOption) error {
	return c.internalClient.DeleteFolder(ctx, req, opts...)
}

// GetFolder returns metadata for the specified folder. This operation is only
// applicable to a hierarchical namespace enabled bucket.
// Hierarchical namespace buckets are in allowlist preview.
func (c *StorageControlClient) GetFolder(ctx context.Context, req *controlpb.GetFolderRequest, opts ...gax.CallOption) (*controlpb.Folder, error) {
	return c.internalClient.GetFolder(ctx, req, opts...)
}

// ListFolders retrieves a list of folders. This operation is only applicable to a
// hierarchical namespace enabled bucket.
// Hierarchical namespace buckets are in allowlist preview.
func (c *StorageControlClient) ListFolders(ctx context.Context, req *controlpb.ListFoldersRequest, opts ...gax.CallOption) *FolderIterator {
	return c.internalClient.ListFolders(ctx, req, opts...)
}

// RenameFolder renames a source folder to a destination folder. This operation is only
// applicable to a hierarchical namespace enabled bucket. During a rename, the
// source and destination folders are locked until the long running operation
// completes.
// Hierarchical namespace buckets are in allowlist preview.
func (c *StorageControlClient) RenameFolder(ctx context.Context, req *controlpb.RenameFolderRequest, opts ...gax.CallOption) (*RenameFolderOperation, error) {
	return c.internalClient.RenameFolder(ctx, req, opts...)
}

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

// GetStorageLayout returns the storage layout configuration for a given bucket.
func (c *StorageControlClient) GetStorageLayout(ctx context.Context, req *controlpb.GetStorageLayoutRequest, opts ...gax.CallOption) (*controlpb.StorageLayout, error) {
	return c.internalClient.GetStorageLayout(ctx, req, opts...)
}

// CreateManagedFolder creates a new managed folder.
func (c *StorageControlClient) CreateManagedFolder(ctx context.Context, req *controlpb.CreateManagedFolderRequest, opts ...gax.CallOption) (*controlpb.ManagedFolder, error) {
	return c.internalClient.CreateManagedFolder(ctx, req, opts...)
}

// DeleteManagedFolder permanently deletes an empty managed folder.
func (c *StorageControlClient) DeleteManagedFolder(ctx context.Context, req *controlpb.DeleteManagedFolderRequest, opts ...gax.CallOption) error {
	return c.internalClient.DeleteManagedFolder(ctx, req, opts...)
}

// GetManagedFolder returns metadata for the specified managed folder.
func (c *StorageControlClient) GetManagedFolder(ctx context.Context, req *controlpb.GetManagedFolderRequest, opts ...gax.CallOption) (*controlpb.ManagedFolder, error) {
	return c.internalClient.GetManagedFolder(ctx, req, opts...)
}

// ListManagedFolders retrieves a list of managed folders for a given bucket.
func (c *StorageControlClient) ListManagedFolders(ctx context.Context, req *controlpb.ListManagedFoldersRequest, opts ...gax.CallOption) *ManagedFolderIterator {
	return c.internalClient.ListManagedFolders(ctx, req, opts...)
}

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

	// Points back to the CallOptions field of the containing StorageControlClient
	CallOptions **StorageControlCallOptions

	// The gRPC API client.
	storageControlClient controlpb.StorageControlClient

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

// NewStorageControlClient creates a new storage control client based on gRPC.
// The returned client must be Closed when it is done being used to clean up its underlying connections.
//
// StorageControl service includes selected control plane operations.
func NewStorageControlClient(ctx context.Context, opts ...option.ClientOption) (*StorageControlClient, error) {
	clientOpts := defaultStorageControlGRPCClientOptions()
	if newStorageControlClientHook != nil {
		hookOpts, err := newStorageControlClientHook(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 := StorageControlClient{CallOptions: defaultStorageControlCallOptions()}

	c := &storageControlGRPCClient{
		connPool:             connPool,
		storageControlClient: controlpb.NewStorageControlClient(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 *storageControlGRPCClient) 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 *storageControlGRPCClient) 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 *storageControlGRPCClient) Close() error {
	return c.connPool.Close()
}

func (c *storageControlGRPCClient) CreateFolder(ctx context.Context, req *controlpb.CreateFolderRequest, opts ...gax.CallOption) (*controlpb.Folder, error) {
	routingHeaders := ""
	routingHeadersMap := make(map[string]string)
	if reg := regexp.MustCompile("(?P<bucket>.*)"); reg.MatchString(req.GetParent()) && len(url.QueryEscape(reg.FindStringSubmatch(req.GetParent())[1])) > 0 {
		routingHeadersMap["bucket"] = url.QueryEscape(reg.FindStringSubmatch(req.GetParent())[1])
	}
	for headerName, headerValue := range routingHeadersMap {
		routingHeaders = fmt.Sprintf("%s%s=%s&", routingHeaders, headerName, headerValue)
	}
	routingHeaders = strings.TrimSuffix(routingHeaders, "&")
	hds := []string{"x-goog-request-params", routingHeaders}

	hds = append(c.xGoogHeaders, hds...)
	ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...)
	if req != nil && req.GetRequestId() == "" {
		req.RequestId = uuid.NewString()
	}
	opts = append((*c.CallOptions).CreateFolder[0:len((*c.CallOptions).CreateFolder):len((*c.CallOptions).CreateFolder)], opts...)
	var resp *controlpb.Folder
	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		var err error
		resp, err = c.storageControlClient.CreateFolder(ctx, req, settings.GRPC...)
		return err
	}, opts...)
	if err != nil {
		return nil, err
	}
	return resp, nil
}

func (c *storageControlGRPCClient) DeleteFolder(ctx context.Context, req *controlpb.DeleteFolderRequest, opts ...gax.CallOption) error {
	routingHeaders := ""
	routingHeadersMap := make(map[string]string)
	if reg := regexp.MustCompile("(?P<bucket>projects/[^/]+/buckets/[^/]+)(?:/.*)?"); reg.MatchString(req.GetName()) && len(url.QueryEscape(reg.FindStringSubmatch(req.GetName())[1])) > 0 {
		routingHeadersMap["bucket"] = url.QueryEscape(reg.FindStringSubmatch(req.GetName())[1])
	}
	for headerName, headerValue := range routingHeadersMap {
		routingHeaders = fmt.Sprintf("%s%s=%s&", routingHeaders, headerName, headerValue)
	}
	routingHeaders = strings.TrimSuffix(routingHeaders, "&")
	hds := []string{"x-goog-request-params", routingHeaders}

	hds = append(c.xGoogHeaders, hds...)
	ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...)
	if req != nil && req.GetRequestId() == "" {
		req.RequestId = uuid.NewString()
	}
	opts = append((*c.CallOptions).DeleteFolder[0:len((*c.CallOptions).DeleteFolder):len((*c.CallOptions).DeleteFolder)], opts...)
	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		var err error
		_, err = c.storageControlClient.DeleteFolder(ctx, req, settings.GRPC...)
		return err
	}, opts...)
	return err
}

func (c *storageControlGRPCClient) GetFolder(ctx context.Context, req *controlpb.GetFolderRequest, opts ...gax.CallOption) (*controlpb.Folder, error) {
	routingHeaders := ""
	routingHeadersMap := make(map[string]string)
	if reg := regexp.MustCompile("(?P<bucket>projects/[^/]+/buckets/[^/]+)(?:/.*)?"); reg.MatchString(req.GetName()) && len(url.QueryEscape(reg.FindStringSubmatch(req.GetName())[1])) > 0 {
		routingHeadersMap["bucket"] = url.QueryEscape(reg.FindStringSubmatch(req.GetName())[1])
	}
	for headerName, headerValue := range routingHeadersMap {
		routingHeaders = fmt.Sprintf("%s%s=%s&", routingHeaders, headerName, headerValue)
	}
	routingHeaders = strings.TrimSuffix(routingHeaders, "&")
	hds := []string{"x-goog-request-params", routingHeaders}

	hds = append(c.xGoogHeaders, hds...)
	ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...)
	if req != nil && req.GetRequestId() == "" {
		req.RequestId = uuid.NewString()
	}
	opts = append((*c.CallOptions).GetFolder[0:len((*c.CallOptions).GetFolder):len((*c.CallOptions).GetFolder)], opts...)
	var resp *controlpb.Folder
	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		var err error
		resp, err = c.storageControlClient.GetFolder(ctx, req, settings.GRPC...)
		return err
	}, opts...)
	if err != nil {
		return nil, err
	}
	return resp, nil
}

func (c *storageControlGRPCClient) ListFolders(ctx context.Context, req *controlpb.ListFoldersRequest, opts ...gax.CallOption) *FolderIterator {
	routingHeaders := ""
	routingHeadersMap := make(map[string]string)
	if reg := regexp.MustCompile("(?P<bucket>.*)"); reg.MatchString(req.GetParent()) && len(url.QueryEscape(reg.FindStringSubmatch(req.GetParent())[1])) > 0 {
		routingHeadersMap["bucket"] = url.QueryEscape(reg.FindStringSubmatch(req.GetParent())[1])
	}
	for headerName, headerValue := range routingHeadersMap {
		routingHeaders = fmt.Sprintf("%s%s=%s&", routingHeaders, headerName, headerValue)
	}
	routingHeaders = strings.TrimSuffix(routingHeaders, "&")
	hds := []string{"x-goog-request-params", routingHeaders}

	hds = append(c.xGoogHeaders, hds...)
	ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...)
	opts = append((*c.CallOptions).ListFolders[0:len((*c.CallOptions).ListFolders):len((*c.CallOptions).ListFolders)], opts...)
	it := &FolderIterator{}
	req = proto.Clone(req).(*controlpb.ListFoldersRequest)
	it.InternalFetch = func(pageSize int, pageToken string) ([]*controlpb.Folder, string, error) {
		resp := &controlpb.ListFoldersResponse{}
		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.storageControlClient.ListFolders(ctx, req, settings.GRPC...)
			return err
		}, opts...)
		if err != nil {
			return nil, "", err
		}

		it.Response = resp
		return resp.GetFolders(), 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 *storageControlGRPCClient) RenameFolder(ctx context.Context, req *controlpb.RenameFolderRequest, opts ...gax.CallOption) (*RenameFolderOperation, error) {
	routingHeaders := ""
	routingHeadersMap := make(map[string]string)
	if reg := regexp.MustCompile("(?P<bucket>projects/[^/]+/buckets/[^/]+)(?:/.*)?"); reg.MatchString(req.GetName()) && len(url.QueryEscape(reg.FindStringSubmatch(req.GetName())[1])) > 0 {
		routingHeadersMap["bucket"] = url.QueryEscape(reg.FindStringSubmatch(req.GetName())[1])
	}
	for headerName, headerValue := range routingHeadersMap {
		routingHeaders = fmt.Sprintf("%s%s=%s&", routingHeaders, headerName, headerValue)
	}
	routingHeaders = strings.TrimSuffix(routingHeaders, "&")
	hds := []string{"x-goog-request-params", routingHeaders}

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

func (c *storageControlGRPCClient) GetStorageLayout(ctx context.Context, req *controlpb.GetStorageLayoutRequest, opts ...gax.CallOption) (*controlpb.StorageLayout, error) {
	routingHeaders := ""
	routingHeadersMap := make(map[string]string)
	if reg := regexp.MustCompile("(?P<bucket>projects/[^/]+/buckets/[^/]+)(?:/.*)?"); reg.MatchString(req.GetName()) && len(url.QueryEscape(reg.FindStringSubmatch(req.GetName())[1])) > 0 {
		routingHeadersMap["bucket"] = url.QueryEscape(reg.FindStringSubmatch(req.GetName())[1])
	}
	for headerName, headerValue := range routingHeadersMap {
		routingHeaders = fmt.Sprintf("%s%s=%s&", routingHeaders, headerName, headerValue)
	}
	routingHeaders = strings.TrimSuffix(routingHeaders, "&")
	hds := []string{"x-goog-request-params", routingHeaders}

	hds = append(c.xGoogHeaders, hds...)
	ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...)
	if req != nil && req.GetRequestId() == "" {
		req.RequestId = uuid.NewString()
	}
	opts = append((*c.CallOptions).GetStorageLayout[0:len((*c.CallOptions).GetStorageLayout):len((*c.CallOptions).GetStorageLayout)], opts...)
	var resp *controlpb.StorageLayout
	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		var err error
		resp, err = c.storageControlClient.GetStorageLayout(ctx, req, settings.GRPC...)
		return err
	}, opts...)
	if err != nil {
		return nil, err
	}
	return resp, nil
}

func (c *storageControlGRPCClient) CreateManagedFolder(ctx context.Context, req *controlpb.CreateManagedFolderRequest, opts ...gax.CallOption) (*controlpb.ManagedFolder, error) {
	routingHeaders := ""
	routingHeadersMap := make(map[string]string)
	if reg := regexp.MustCompile("(?P<bucket>.*)"); reg.MatchString(req.GetParent()) && len(url.QueryEscape(reg.FindStringSubmatch(req.GetParent())[1])) > 0 {
		routingHeadersMap["bucket"] = url.QueryEscape(reg.FindStringSubmatch(req.GetParent())[1])
	}
	for headerName, headerValue := range routingHeadersMap {
		routingHeaders = fmt.Sprintf("%s%s=%s&", routingHeaders, headerName, headerValue)
	}
	routingHeaders = strings.TrimSuffix(routingHeaders, "&")
	hds := []string{"x-goog-request-params", routingHeaders}

	hds = append(c.xGoogHeaders, hds...)
	ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...)
	if req != nil && req.GetRequestId() == "" {
		req.RequestId = uuid.NewString()
	}
	opts = append((*c.CallOptions).CreateManagedFolder[0:len((*c.CallOptions).CreateManagedFolder):len((*c.CallOptions).CreateManagedFolder)], opts...)
	var resp *controlpb.ManagedFolder
	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		var err error
		resp, err = c.storageControlClient.CreateManagedFolder(ctx, req, settings.GRPC...)
		return err
	}, opts...)
	if err != nil {
		return nil, err
	}
	return resp, nil
}

func (c *storageControlGRPCClient) DeleteManagedFolder(ctx context.Context, req *controlpb.DeleteManagedFolderRequest, opts ...gax.CallOption) error {
	routingHeaders := ""
	routingHeadersMap := make(map[string]string)
	if reg := regexp.MustCompile("(?P<bucket>projects/[^/]+/buckets/[^/]+)(?:/.*)?"); reg.MatchString(req.GetName()) && len(url.QueryEscape(reg.FindStringSubmatch(req.GetName())[1])) > 0 {
		routingHeadersMap["bucket"] = url.QueryEscape(reg.FindStringSubmatch(req.GetName())[1])
	}
	for headerName, headerValue := range routingHeadersMap {
		routingHeaders = fmt.Sprintf("%s%s=%s&", routingHeaders, headerName, headerValue)
	}
	routingHeaders = strings.TrimSuffix(routingHeaders, "&")
	hds := []string{"x-goog-request-params", routingHeaders}

	hds = append(c.xGoogHeaders, hds...)
	ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...)
	if req != nil && req.GetRequestId() == "" {
		req.RequestId = uuid.NewString()
	}
	opts = append((*c.CallOptions).DeleteManagedFolder[0:len((*c.CallOptions).DeleteManagedFolder):len((*c.CallOptions).DeleteManagedFolder)], opts...)
	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		var err error
		_, err = c.storageControlClient.DeleteManagedFolder(ctx, req, settings.GRPC...)
		return err
	}, opts...)
	return err
}

func (c *storageControlGRPCClient) GetManagedFolder(ctx context.Context, req *controlpb.GetManagedFolderRequest, opts ...gax.CallOption) (*controlpb.ManagedFolder, error) {
	routingHeaders := ""
	routingHeadersMap := make(map[string]string)
	if reg := regexp.MustCompile("(?P<bucket>projects/[^/]+/buckets/[^/]+)(?:/.*)?"); reg.MatchString(req.GetName()) && len(url.QueryEscape(reg.FindStringSubmatch(req.GetName())[1])) > 0 {
		routingHeadersMap["bucket"] = url.QueryEscape(reg.FindStringSubmatch(req.GetName())[1])
	}
	for headerName, headerValue := range routingHeadersMap {
		routingHeaders = fmt.Sprintf("%s%s=%s&", routingHeaders, headerName, headerValue)
	}
	routingHeaders = strings.TrimSuffix(routingHeaders, "&")
	hds := []string{"x-goog-request-params", routingHeaders}

	hds = append(c.xGoogHeaders, hds...)
	ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...)
	if req != nil && req.GetRequestId() == "" {
		req.RequestId = uuid.NewString()
	}
	opts = append((*c.CallOptions).GetManagedFolder[0:len((*c.CallOptions).GetManagedFolder):len((*c.CallOptions).GetManagedFolder)], opts...)
	var resp *controlpb.ManagedFolder
	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		var err error
		resp, err = c.storageControlClient.GetManagedFolder(ctx, req, settings.GRPC...)
		return err
	}, opts...)
	if err != nil {
		return nil, err
	}
	return resp, nil
}

func (c *storageControlGRPCClient) ListManagedFolders(ctx context.Context, req *controlpb.ListManagedFoldersRequest, opts ...gax.CallOption) *ManagedFolderIterator {
	routingHeaders := ""
	routingHeadersMap := make(map[string]string)
	if reg := regexp.MustCompile("(?P<bucket>.*)"); reg.MatchString(req.GetParent()) && len(url.QueryEscape(reg.FindStringSubmatch(req.GetParent())[1])) > 0 {
		routingHeadersMap["bucket"] = url.QueryEscape(reg.FindStringSubmatch(req.GetParent())[1])
	}
	for headerName, headerValue := range routingHeadersMap {
		routingHeaders = fmt.Sprintf("%s%s=%s&", routingHeaders, headerName, headerValue)
	}
	routingHeaders = strings.TrimSuffix(routingHeaders, "&")
	hds := []string{"x-goog-request-params", routingHeaders}

	hds = append(c.xGoogHeaders, hds...)
	ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...)
	opts = append((*c.CallOptions).ListManagedFolders[0:len((*c.CallOptions).ListManagedFolders):len((*c.CallOptions).ListManagedFolders)], opts...)
	it := &ManagedFolderIterator{}
	req = proto.Clone(req).(*controlpb.ListManagedFoldersRequest)
	it.InternalFetch = func(pageSize int, pageToken string) ([]*controlpb.ManagedFolder, string, error) {
		resp := &controlpb.ListManagedFoldersResponse{}
		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.storageControlClient.ListManagedFolders(ctx, req, settings.GRPC...)
			return err
		}, opts...)
		if err != nil {
			return nil, "", err
		}

		it.Response = resp
		return resp.GetManagedFolders(), 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
}

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