// Copyright 2020 Google LLC.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Code generated file. DO NOT EDIT.

// Package billingbudgets provides access to the Cloud Billing Budget API.
//
// For product documentation, see: https://cloud.google.com/billing/docs/how-to/budget-api-overview
//
// Creating a client
//
// Usage example:
//
//   import "google.golang.org/api/billingbudgets/v1beta1"
//   ...
//   ctx := context.Background()
//   billingbudgetsService, err := billingbudgets.NewService(ctx)
//
// In this example, Google Application Default Credentials are used for authentication.
//
// For information on how to create and obtain Application Default Credentials, see https://developers.google.com/identity/protocols/application-default-credentials.
//
// Other authentication options
//
// By default, all available scopes (see "Constants") are used to authenticate. To restrict scopes, use option.WithScopes:
//
//   billingbudgetsService, err := billingbudgets.NewService(ctx, option.WithScopes(billingbudgets.CloudPlatformScope))
//
// To use an API key for authentication (note: some APIs do not support API keys), use option.WithAPIKey:
//
//   billingbudgetsService, err := billingbudgets.NewService(ctx, option.WithAPIKey("AIza..."))
//
// To use an OAuth token (e.g., a user token obtained via a three-legged OAuth flow), use option.WithTokenSource:
//
//   config := &oauth2.Config{...}
//   // ...
//   token, err := config.Exchange(ctx, ...)
//   billingbudgetsService, err := billingbudgets.NewService(ctx, option.WithTokenSource(config.TokenSource(ctx, token)))
//
// See https://godoc.org/google.golang.org/api/option/ for details on options.
package billingbudgets // import "google.golang.org/api/billingbudgets/v1beta1"

import (
	"bytes"
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"strconv"
	"strings"

	googleapi "google.golang.org/api/googleapi"
	gensupport "google.golang.org/api/internal/gensupport"
	option "google.golang.org/api/option"
	internaloption "google.golang.org/api/option/internaloption"
	htransport "google.golang.org/api/transport/http"
)

// Always reference these packages, just in case the auto-generated code
// below doesn't.
var _ = bytes.NewBuffer
var _ = strconv.Itoa
var _ = fmt.Sprintf
var _ = json.NewDecoder
var _ = io.Copy
var _ = url.Parse
var _ = gensupport.MarshalJSON
var _ = googleapi.Version
var _ = errors.New
var _ = strings.Replace
var _ = context.Canceled
var _ = internaloption.WithDefaultEndpoint

const apiId = "billingbudgets:v1beta1"
const apiName = "billingbudgets"
const apiVersion = "v1beta1"
const basePath = "https://billingbudgets.googleapis.com/"
const mtlsBasePath = "https://billingbudgets.mtls.googleapis.com/"

// OAuth2 scopes used by this API.
const (
	// View and manage your Google Cloud Platform billing accounts
	CloudBillingScope = "https://www.googleapis.com/auth/cloud-billing"

	// View and manage your data across Google Cloud Platform services
	CloudPlatformScope = "https://www.googleapis.com/auth/cloud-platform"
)

// NewService creates a new Service.
func NewService(ctx context.Context, opts ...option.ClientOption) (*Service, error) {
	scopesOption := option.WithScopes(
		"https://www.googleapis.com/auth/cloud-billing",
		"https://www.googleapis.com/auth/cloud-platform",
	)
	// NOTE: prepend, so we don't override user-specified scopes.
	opts = append([]option.ClientOption{scopesOption}, opts...)
	opts = append(opts, internaloption.WithDefaultEndpoint(basePath))
	opts = append(opts, internaloption.WithDefaultMTLSEndpoint(mtlsBasePath))
	client, endpoint, err := htransport.NewClient(ctx, opts...)
	if err != nil {
		return nil, err
	}
	s, err := New(client)
	if err != nil {
		return nil, err
	}
	if endpoint != "" {
		s.BasePath = endpoint
	}
	return s, nil
}

// New creates a new Service. It uses the provided http.Client for requests.
//
// Deprecated: please use NewService instead.
// To provide a custom HTTP client, use option.WithHTTPClient.
// If you are using google.golang.org/api/googleapis/transport.APIKey, use option.WithAPIKey with NewService instead.
func New(client *http.Client) (*Service, error) {
	if client == nil {
		return nil, errors.New("client is nil")
	}
	s := &Service{client: client, BasePath: basePath}
	s.BillingAccounts = NewBillingAccountsService(s)
	return s, nil
}

type Service struct {
	client    *http.Client
	BasePath  string // API endpoint base URL
	UserAgent string // optional additional User-Agent fragment

	BillingAccounts *BillingAccountsService
}

func (s *Service) userAgent() string {
	if s.UserAgent == "" {
		return googleapi.UserAgent
	}
	return googleapi.UserAgent + " " + s.UserAgent
}

func NewBillingAccountsService(s *Service) *BillingAccountsService {
	rs := &BillingAccountsService{s: s}
	rs.Budgets = NewBillingAccountsBudgetsService(s)
	return rs
}

type BillingAccountsService struct {
	s *Service

	Budgets *BillingAccountsBudgetsService
}

func NewBillingAccountsBudgetsService(s *Service) *BillingAccountsBudgetsService {
	rs := &BillingAccountsBudgetsService{s: s}
	return rs
}

type BillingAccountsBudgetsService struct {
	s *Service
}

// GoogleCloudBillingBudgetsV1beta1AllUpdatesRule: AllUpdatesRule
// defines notifications that are sent based on budget spend and
// thresholds.
type GoogleCloudBillingBudgetsV1beta1AllUpdatesRule struct {
	// MonitoringNotificationChannels: Optional. Targets to send
	// notifications to when a threshold is exceeded. This is in addition to
	// default recipients who have billing account roles. The value is the
	// full REST resource name of a monitoring notification channel with the
	// form `projects/{project_id}/notificationChannels/{channel_id}`. A
	// maximum of 5 channels are allowed. See
	// https://cloud.google.com/billing/docs/how-to/budgets-notification-recipients for more
	// details.
	MonitoringNotificationChannels []string `json:"monitoringNotificationChannels,omitempty"`

	// PubsubTopic: Optional. The name of the Pub/Sub topic where budget
	// related messages will be published, in the form
	// `projects/{project_id}/topics/{topic_id}`. Updates are sent at
	// regular intervals to the topic. The topic needs to be created before
	// the budget is created; see
	// https://cloud.google.com/billing/docs/how-to/budgets#manage-notifications for more details. Caller is expected to have `pubsub.topics.setIamPolicy` permission on the topic when it's set for a budget, otherwise, the API call will fail with PERMISSION_DENIED. See https://cloud.google.com/billing/docs/how-to/budgets-programmatic-notifications for more details on Pub/Sub roles and
	// permissions.
	PubsubTopic string `json:"pubsubTopic,omitempty"`

	// SchemaVersion: Optional. The schema version of the notification sent
	// to `pubsub_topic`. Only "1.0" is accepted. It represents the JSON
	// schema as defined in
	// https://cloud.google.com/billing/docs/how-to/budgets-programmatic-notifications#notification_format
	SchemaVersion string `json:"schemaVersion,omitempty"`

	// ForceSendFields is a list of field names (e.g.
	// "MonitoringNotificationChannels") to unconditionally include in API
	// requests. By default, fields with empty values are omitted from API
	// requests. However, any non-pointer, non-interface field appearing in
	// ForceSendFields will be sent to the server regardless of whether the
	// field is empty or not. This may be used to include empty fields in
	// Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g.
	// "MonitoringNotificationChannels") to include in API requests with the
	// JSON null value. By default, fields with empty values are omitted
	// from API requests. However, any field with an empty value appearing
	// in NullFields will be sent to the server as null. It is an error if a
	// field in this list has a non-empty value. This may be used to include
	// null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudBillingBudgetsV1beta1AllUpdatesRule) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudBillingBudgetsV1beta1AllUpdatesRule
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudBillingBudgetsV1beta1Budget: A budget is a plan that
// describes what you expect to spend on Cloud projects, plus the rules
// to execute as spend is tracked against that plan, (for example, send
// an alert when 90% of the target spend is met). Currently all plans
// are monthly budgets so the usage period(s) tracked are implied
// (calendar months of usage back-to-back).
type GoogleCloudBillingBudgetsV1beta1Budget struct {
	// AllUpdatesRule: Optional. Rules to apply to notifications sent based
	// on budget spend and thresholds.
	AllUpdatesRule *GoogleCloudBillingBudgetsV1beta1AllUpdatesRule `json:"allUpdatesRule,omitempty"`

	// Amount: Required. Budgeted amount.
	Amount *GoogleCloudBillingBudgetsV1beta1BudgetAmount `json:"amount,omitempty"`

	// BudgetFilter: Optional. Filters that define which resources are used
	// to compute the actual spend against the budget.
	BudgetFilter *GoogleCloudBillingBudgetsV1beta1Filter `json:"budgetFilter,omitempty"`

	// DisplayName: User data for display name in UI. Validation: <= 60
	// chars.
	DisplayName string `json:"displayName,omitempty"`

	// Etag: Optional. Etag to validate that the object is unchanged for a
	// read-modify-write operation. An empty etag will cause an update to
	// overwrite other changes.
	Etag string `json:"etag,omitempty"`

	// Name: Output only. Resource name of the budget. The resource name
	// implies the scope of a budget. Values are of the form
	// `billingAccounts/{billingAccountId}/budgets/{budgetId}`.
	Name string `json:"name,omitempty"`

	// ThresholdRules: Optional. Rules that trigger alerts (notifications of
	// thresholds being crossed) when spend exceeds the specified
	// percentages of the budget.
	ThresholdRules []*GoogleCloudBillingBudgetsV1beta1ThresholdRule `json:"thresholdRules,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the
	// server.
	googleapi.ServerResponse `json:"-"`

	// ForceSendFields is a list of field names (e.g. "AllUpdatesRule") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "AllUpdatesRule") to
	// include in API requests with the JSON null value. By default, fields
	// with empty values are omitted from API requests. However, any field
	// with an empty value appearing in NullFields will be sent to the
	// server as null. It is an error if a field in this list has a
	// non-empty value. This may be used to include null fields in Patch
	// requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudBillingBudgetsV1beta1Budget) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudBillingBudgetsV1beta1Budget
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudBillingBudgetsV1beta1BudgetAmount: The budgeted amount for
// each usage period.
type GoogleCloudBillingBudgetsV1beta1BudgetAmount struct {
	// LastPeriodAmount: Use the last period's actual spend as the budget
	// for the present period.
	LastPeriodAmount *GoogleCloudBillingBudgetsV1beta1LastPeriodAmount `json:"lastPeriodAmount,omitempty"`

	// SpecifiedAmount: A specified amount to use as the budget.
	// `currency_code` is optional. If specified, it must match the currency
	// of the billing account. The `currency_code` is provided on output.
	SpecifiedAmount *GoogleTypeMoney `json:"specifiedAmount,omitempty"`

	// ForceSendFields is a list of field names (e.g. "LastPeriodAmount") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "LastPeriodAmount") to
	// include in API requests with the JSON null value. By default, fields
	// with empty values are omitted from API requests. However, any field
	// with an empty value appearing in NullFields will be sent to the
	// server as null. It is an error if a field in this list has a
	// non-empty value. This may be used to include null fields in Patch
	// requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudBillingBudgetsV1beta1BudgetAmount) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudBillingBudgetsV1beta1BudgetAmount
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudBillingBudgetsV1beta1CreateBudgetRequest: Request for
// CreateBudget
type GoogleCloudBillingBudgetsV1beta1CreateBudgetRequest struct {
	// Budget: Required. Budget to create.
	Budget *GoogleCloudBillingBudgetsV1beta1Budget `json:"budget,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Budget") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Budget") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudBillingBudgetsV1beta1CreateBudgetRequest) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudBillingBudgetsV1beta1CreateBudgetRequest
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudBillingBudgetsV1beta1Filter: A filter for a budget,
// limiting the scope of the cost to calculate.
type GoogleCloudBillingBudgetsV1beta1Filter struct {
	// CreditTypesTreatment: Optional. If not set, default behavior is
	// `INCLUDE_ALL_CREDITS`.
	//
	// Possible values:
	//   "CREDIT_TYPES_TREATMENT_UNSPECIFIED"
	//   "INCLUDE_ALL_CREDITS" - All types of credit are subtracted from the
	// gross cost to determine the spend for threshold calculations.
	//   "EXCLUDE_ALL_CREDITS" - All types of credit are added to the net
	// cost to determine the spend for threshold calculations.
	CreditTypesTreatment string `json:"creditTypesTreatment,omitempty"`

	// Labels: Optional. A single label and value pair specifying that usage
	// from only this set of labeled resources should be included in the
	// budget. Currently, multiple entries or multiple values per entry are
	// not allowed. If omitted, the report will include all labeled and
	// unlabeled usage.
	Labels map[string][]interface{} `json:"labels,omitempty"`

	// Projects: Optional. A set of projects of the form
	// `projects/{project}`, specifying that usage from only this set of
	// projects should be included in the budget. If omitted, the report
	// will include all usage for the billing account, regardless of which
	// project the usage occurred on. Only zero or one project can be
	// specified currently.
	Projects []string `json:"projects,omitempty"`

	// Services: Optional. A set of services of the form
	// `services/{service_id}`, specifying that usage from only this set of
	// services should be included in the budget. If omitted, the report
	// will include usage for all the services. The service names are
	// available through the Catalog API:
	// https://cloud.google.com/billing/v1/how-tos/catalog-api.
	Services []string `json:"services,omitempty"`

	// Subaccounts: Optional. A set of subaccounts of the form
	// `billingAccounts/{account_id}`, specifying that usage from only this
	// set of subaccounts should be included in the budget. If a subaccount
	// is set to the name of the parent account, usage from the parent
	// account will be included. If omitted, the report will include usage
	// from the parent account and all subaccounts, if they exist.
	Subaccounts []string `json:"subaccounts,omitempty"`

	// ForceSendFields is a list of field names (e.g.
	// "CreditTypesTreatment") to unconditionally include in API requests.
	// By default, fields with empty values are omitted from API requests.
	// However, any non-pointer, non-interface field appearing in
	// ForceSendFields will be sent to the server regardless of whether the
	// field is empty or not. This may be used to include empty fields in
	// Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "CreditTypesTreatment") to
	// include in API requests with the JSON null value. By default, fields
	// with empty values are omitted from API requests. However, any field
	// with an empty value appearing in NullFields will be sent to the
	// server as null. It is an error if a field in this list has a
	// non-empty value. This may be used to include null fields in Patch
	// requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudBillingBudgetsV1beta1Filter) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudBillingBudgetsV1beta1Filter
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudBillingBudgetsV1beta1LastPeriodAmount: Describes a budget
// amount targeted to last period's spend. At this time, the amount is
// automatically 100% of last period's spend; that is, there are no
// other options yet. Future configuration will be described here (for
// example, configuring a percentage of last period's spend).
type GoogleCloudBillingBudgetsV1beta1LastPeriodAmount struct {
}

// GoogleCloudBillingBudgetsV1beta1ListBudgetsResponse: Response for
// ListBudgets
type GoogleCloudBillingBudgetsV1beta1ListBudgetsResponse struct {
	// Budgets: List of the budgets owned by the requested billing account.
	Budgets []*GoogleCloudBillingBudgetsV1beta1Budget `json:"budgets,omitempty"`

	// NextPageToken: If not empty, indicates that there may be more budgets
	// that match the request; this value should be passed in a new
	// `ListBudgetsRequest`.
	NextPageToken string `json:"nextPageToken,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the
	// server.
	googleapi.ServerResponse `json:"-"`

	// ForceSendFields is a list of field names (e.g. "Budgets") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Budgets") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudBillingBudgetsV1beta1ListBudgetsResponse) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudBillingBudgetsV1beta1ListBudgetsResponse
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudBillingBudgetsV1beta1ThresholdRule: ThresholdRule contains
// a definition of a threshold which triggers an alert (a notification
// of a threshold being crossed) to be sent when spend goes above the
// specified amount. Alerts are automatically e-mailed to users with the
// Billing Account Administrator role or the Billing Account User role.
// The thresholds here have no effect on notifications sent to anything
// configured under `Budget.all_updates_rule`.
type GoogleCloudBillingBudgetsV1beta1ThresholdRule struct {
	// SpendBasis: Optional. The type of basis used to determine if spend
	// has passed the threshold. Behavior defaults to CURRENT_SPEND if not
	// set.
	//
	// Possible values:
	//   "BASIS_UNSPECIFIED" - Unspecified threshold basis.
	//   "CURRENT_SPEND" - Use current spend as the basis for comparison
	// against the threshold.
	//   "FORECASTED_SPEND" - Use forecasted spend for the period as the
	// basis for comparison against the threshold.
	SpendBasis string `json:"spendBasis,omitempty"`

	// ThresholdPercent: Required. Send an alert when this threshold is
	// exceeded. This is a 1.0-based percentage, so 0.5 = 50%. Validation:
	// non-negative number.
	ThresholdPercent float64 `json:"thresholdPercent,omitempty"`

	// ForceSendFields is a list of field names (e.g. "SpendBasis") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "SpendBasis") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudBillingBudgetsV1beta1ThresholdRule) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudBillingBudgetsV1beta1ThresholdRule
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

func (s *GoogleCloudBillingBudgetsV1beta1ThresholdRule) UnmarshalJSON(data []byte) error {
	type NoMethod GoogleCloudBillingBudgetsV1beta1ThresholdRule
	var s1 struct {
		ThresholdPercent gensupport.JSONFloat64 `json:"thresholdPercent"`
		*NoMethod
	}
	s1.NoMethod = (*NoMethod)(s)
	if err := json.Unmarshal(data, &s1); err != nil {
		return err
	}
	s.ThresholdPercent = float64(s1.ThresholdPercent)
	return nil
}

// GoogleCloudBillingBudgetsV1beta1UpdateBudgetRequest: Request for
// UpdateBudget
type GoogleCloudBillingBudgetsV1beta1UpdateBudgetRequest struct {
	// Budget: Required. The updated budget object. The budget to update is
	// specified by the budget name in the budget.
	Budget *GoogleCloudBillingBudgetsV1beta1Budget `json:"budget,omitempty"`

	// UpdateMask: Optional. Indicates which fields in the provided budget
	// to update. Read-only fields (such as `name`) cannot be changed. If
	// this is not provided, then only fields with non-default values from
	// the request are updated. See
	// https://developers.google.com/protocol-buffers/docs/proto3#default
	// for more details about default values.
	UpdateMask string `json:"updateMask,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Budget") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Budget") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudBillingBudgetsV1beta1UpdateBudgetRequest) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudBillingBudgetsV1beta1UpdateBudgetRequest
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleProtobufEmpty: A generic empty message that you can re-use to
// avoid defining duplicated empty messages in your APIs. A typical
// example is to use it as the request or the response type of an API
// method. For instance: service Foo { rpc Bar(google.protobuf.Empty)
// returns (google.protobuf.Empty); } The JSON representation for
// `Empty` is empty JSON object `{}`.
type GoogleProtobufEmpty struct {
	// ServerResponse contains the HTTP response code and headers from the
	// server.
	googleapi.ServerResponse `json:"-"`
}

// GoogleTypeMoney: Represents an amount of money with its currency
// type.
type GoogleTypeMoney struct {
	// CurrencyCode: The 3-letter currency code defined in ISO 4217.
	CurrencyCode string `json:"currencyCode,omitempty"`

	// Nanos: Number of nano (10^-9) units of the amount. The value must be
	// between -999,999,999 and +999,999,999 inclusive. If `units` is
	// positive, `nanos` must be positive or zero. If `units` is zero,
	// `nanos` can be positive, zero, or negative. If `units` is negative,
	// `nanos` must be negative or zero. For example $-1.75 is represented
	// as `units`=-1 and `nanos`=-750,000,000.
	Nanos int64 `json:"nanos,omitempty"`

	// Units: The whole units of the amount. For example if `currencyCode`
	// is "USD", then 1 unit is one US dollar.
	Units int64 `json:"units,omitempty,string"`

	// ForceSendFields is a list of field names (e.g. "CurrencyCode") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "CurrencyCode") to include
	// in API requests with the JSON null value. By default, fields with
	// empty values are omitted from API requests. However, any field with
	// an empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleTypeMoney) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleTypeMoney
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// method id "billingbudgets.billingAccounts.budgets.create":

type BillingAccountsBudgetsCreateCall struct {
	s                                                   *Service
	parent                                              string
	googlecloudbillingbudgetsv1beta1createbudgetrequest *GoogleCloudBillingBudgetsV1beta1CreateBudgetRequest
	urlParams_                                          gensupport.URLParams
	ctx_                                                context.Context
	header_                                             http.Header
}

// Create: Creates a new budget. See Quotas and limits for more
// information on the limits of the number of budgets you can create.
func (r *BillingAccountsBudgetsService) Create(parent string, googlecloudbillingbudgetsv1beta1createbudgetrequest *GoogleCloudBillingBudgetsV1beta1CreateBudgetRequest) *BillingAccountsBudgetsCreateCall {
	c := &BillingAccountsBudgetsCreateCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	c.googlecloudbillingbudgetsv1beta1createbudgetrequest = googlecloudbillingbudgetsv1beta1createbudgetrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
// for more information.
func (c *BillingAccountsBudgetsCreateCall) Fields(s ...googleapi.Field) *BillingAccountsBudgetsCreateCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method. Any
// pending HTTP request will be aborted if the provided context is
// canceled.
func (c *BillingAccountsBudgetsCreateCall) Context(ctx context.Context) *BillingAccountsBudgetsCreateCall {
	c.ctx_ = ctx
	return c
}

// Header returns an http.Header that can be modified by the caller to
// add HTTP headers to the request.
func (c *BillingAccountsBudgetsCreateCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *BillingAccountsBudgetsCreateCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := make(http.Header)
	reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200902")
	for k, v := range c.header_ {
		reqHeaders[k] = v
	}
	reqHeaders.Set("User-Agent", c.s.userAgent())
	var body io.Reader = nil
	body, err := googleapi.WithoutDataWrapper.JSONReader(c.googlecloudbillingbudgetsv1beta1createbudgetrequest)
	if err != nil {
		return nil, err
	}
	reqHeaders.Set("Content-Type", "application/json")
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1beta1/{+parent}/budgets")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "billingbudgets.billingAccounts.budgets.create" call.
// Exactly one of *GoogleCloudBillingBudgetsV1beta1Budget or error will
// be non-nil. Any non-2xx status code is an error. Response headers are
// in either
// *GoogleCloudBillingBudgetsV1beta1Budget.ServerResponse.Header or (if
// a response was returned at all) in error.(*googleapi.Error).Header.
// Use googleapi.IsNotModified to check whether the returned error was
// because http.StatusNotModified was returned.
func (c *BillingAccountsBudgetsCreateCall) Do(opts ...googleapi.CallOption) (*GoogleCloudBillingBudgetsV1beta1Budget, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, &googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		}
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, err
	}
	ret := &GoogleCloudBillingBudgetsV1beta1Budget{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	if err := gensupport.DecodeResponse(target, res); err != nil {
		return nil, err
	}
	return ret, nil
	// {
	//   "description": "Creates a new budget. See Quotas and limits for more information on the limits of the number of budgets you can create.",
	//   "flatPath": "v1beta1/billingAccounts/{billingAccountsId}/budgets",
	//   "httpMethod": "POST",
	//   "id": "billingbudgets.billingAccounts.budgets.create",
	//   "parameterOrder": [
	//     "parent"
	//   ],
	//   "parameters": {
	//     "parent": {
	//       "description": "Required. The name of the billing account to create the budget in. Values are of the form `billingAccounts/{billingAccountId}`.",
	//       "location": "path",
	//       "pattern": "^billingAccounts/[^/]+$",
	//       "required": true,
	//       "type": "string"
	//     }
	//   },
	//   "path": "v1beta1/{+parent}/budgets",
	//   "request": {
	//     "$ref": "GoogleCloudBillingBudgetsV1beta1CreateBudgetRequest"
	//   },
	//   "response": {
	//     "$ref": "GoogleCloudBillingBudgetsV1beta1Budget"
	//   },
	//   "scopes": [
	//     "https://www.googleapis.com/auth/cloud-billing",
	//     "https://www.googleapis.com/auth/cloud-platform"
	//   ]
	// }

}

// method id "billingbudgets.billingAccounts.budgets.delete":

type BillingAccountsBudgetsDeleteCall struct {
	s          *Service
	name       string
	urlParams_ gensupport.URLParams
	ctx_       context.Context
	header_    http.Header
}

// Delete: Deletes a budget. Returns successfully if already deleted.
func (r *BillingAccountsBudgetsService) Delete(name string) *BillingAccountsBudgetsDeleteCall {
	c := &BillingAccountsBudgetsDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
// for more information.
func (c *BillingAccountsBudgetsDeleteCall) Fields(s ...googleapi.Field) *BillingAccountsBudgetsDeleteCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method. Any
// pending HTTP request will be aborted if the provided context is
// canceled.
func (c *BillingAccountsBudgetsDeleteCall) Context(ctx context.Context) *BillingAccountsBudgetsDeleteCall {
	c.ctx_ = ctx
	return c
}

// Header returns an http.Header that can be modified by the caller to
// add HTTP headers to the request.
func (c *BillingAccountsBudgetsDeleteCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *BillingAccountsBudgetsDeleteCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := make(http.Header)
	reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200902")
	for k, v := range c.header_ {
		reqHeaders[k] = v
	}
	reqHeaders.Set("User-Agent", c.s.userAgent())
	var body io.Reader = nil
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1beta1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("DELETE", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "billingbudgets.billingAccounts.budgets.delete" call.
// Exactly one of *GoogleProtobufEmpty or error will be non-nil. Any
// non-2xx status code is an error. Response headers are in either
// *GoogleProtobufEmpty.ServerResponse.Header or (if a response was
// returned at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was
// because http.StatusNotModified was returned.
func (c *BillingAccountsBudgetsDeleteCall) Do(opts ...googleapi.CallOption) (*GoogleProtobufEmpty, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, &googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		}
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, err
	}
	ret := &GoogleProtobufEmpty{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	if err := gensupport.DecodeResponse(target, res); err != nil {
		return nil, err
	}
	return ret, nil
	// {
	//   "description": "Deletes a budget. Returns successfully if already deleted.",
	//   "flatPath": "v1beta1/billingAccounts/{billingAccountsId}/budgets/{budgetsId}",
	//   "httpMethod": "DELETE",
	//   "id": "billingbudgets.billingAccounts.budgets.delete",
	//   "parameterOrder": [
	//     "name"
	//   ],
	//   "parameters": {
	//     "name": {
	//       "description": "Required. Name of the budget to delete. Values are of the form `billingAccounts/{billingAccountId}/budgets/{budgetId}`.",
	//       "location": "path",
	//       "pattern": "^billingAccounts/[^/]+/budgets/[^/]+$",
	//       "required": true,
	//       "type": "string"
	//     }
	//   },
	//   "path": "v1beta1/{+name}",
	//   "response": {
	//     "$ref": "GoogleProtobufEmpty"
	//   },
	//   "scopes": [
	//     "https://www.googleapis.com/auth/cloud-billing",
	//     "https://www.googleapis.com/auth/cloud-platform"
	//   ]
	// }

}

// method id "billingbudgets.billingAccounts.budgets.get":

type BillingAccountsBudgetsGetCall struct {
	s            *Service
	name         string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// Get: Returns a budget. WARNING: There are some fields exposed on the
// Google Cloud Console that aren't available on this API. When reading
// from the API, you will not see these fields in the return value,
// though they may have been set in the Cloud Console.
func (r *BillingAccountsBudgetsService) Get(name string) *BillingAccountsBudgetsGetCall {
	c := &BillingAccountsBudgetsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
// for more information.
func (c *BillingAccountsBudgetsGetCall) Fields(s ...googleapi.Field) *BillingAccountsBudgetsGetCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets the optional parameter which makes the operation
// fail if the object's ETag matches the given value. This is useful for
// getting updates only after the object has changed since the last
// request. Use googleapi.IsNotModified to check whether the response
// error from Do is the result of In-None-Match.
func (c *BillingAccountsBudgetsGetCall) IfNoneMatch(entityTag string) *BillingAccountsBudgetsGetCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method. Any
// pending HTTP request will be aborted if the provided context is
// canceled.
func (c *BillingAccountsBudgetsGetCall) Context(ctx context.Context) *BillingAccountsBudgetsGetCall {
	c.ctx_ = ctx
	return c
}

// Header returns an http.Header that can be modified by the caller to
// add HTTP headers to the request.
func (c *BillingAccountsBudgetsGetCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *BillingAccountsBudgetsGetCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := make(http.Header)
	reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200902")
	for k, v := range c.header_ {
		reqHeaders[k] = v
	}
	reqHeaders.Set("User-Agent", c.s.userAgent())
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	var body io.Reader = nil
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1beta1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "billingbudgets.billingAccounts.budgets.get" call.
// Exactly one of *GoogleCloudBillingBudgetsV1beta1Budget or error will
// be non-nil. Any non-2xx status code is an error. Response headers are
// in either
// *GoogleCloudBillingBudgetsV1beta1Budget.ServerResponse.Header or (if
// a response was returned at all) in error.(*googleapi.Error).Header.
// Use googleapi.IsNotModified to check whether the returned error was
// because http.StatusNotModified was returned.
func (c *BillingAccountsBudgetsGetCall) Do(opts ...googleapi.CallOption) (*GoogleCloudBillingBudgetsV1beta1Budget, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, &googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		}
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, err
	}
	ret := &GoogleCloudBillingBudgetsV1beta1Budget{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	if err := gensupport.DecodeResponse(target, res); err != nil {
		return nil, err
	}
	return ret, nil
	// {
	//   "description": "Returns a budget. WARNING: There are some fields exposed on the Google Cloud Console that aren't available on this API. When reading from the API, you will not see these fields in the return value, though they may have been set in the Cloud Console.",
	//   "flatPath": "v1beta1/billingAccounts/{billingAccountsId}/budgets/{budgetsId}",
	//   "httpMethod": "GET",
	//   "id": "billingbudgets.billingAccounts.budgets.get",
	//   "parameterOrder": [
	//     "name"
	//   ],
	//   "parameters": {
	//     "name": {
	//       "description": "Required. Name of budget to get. Values are of the form `billingAccounts/{billingAccountId}/budgets/{budgetId}`.",
	//       "location": "path",
	//       "pattern": "^billingAccounts/[^/]+/budgets/[^/]+$",
	//       "required": true,
	//       "type": "string"
	//     }
	//   },
	//   "path": "v1beta1/{+name}",
	//   "response": {
	//     "$ref": "GoogleCloudBillingBudgetsV1beta1Budget"
	//   },
	//   "scopes": [
	//     "https://www.googleapis.com/auth/cloud-billing",
	//     "https://www.googleapis.com/auth/cloud-platform"
	//   ]
	// }

}

// method id "billingbudgets.billingAccounts.budgets.list":

type BillingAccountsBudgetsListCall struct {
	s            *Service
	parent       string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// List: Returns a list of budgets for a billing account. WARNING: There
// are some fields exposed on the Google Cloud Console that aren't
// available on this API. When reading from the API, you will not see
// these fields in the return value, though they may have been set in
// the Cloud Console.
func (r *BillingAccountsBudgetsService) List(parent string) *BillingAccountsBudgetsListCall {
	c := &BillingAccountsBudgetsListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	return c
}

// PageSize sets the optional parameter "pageSize": The maximum number
// of budgets to return per page. The default and maximum value are 100.
func (c *BillingAccountsBudgetsListCall) PageSize(pageSize int64) *BillingAccountsBudgetsListCall {
	c.urlParams_.Set("pageSize", fmt.Sprint(pageSize))
	return c
}

// PageToken sets the optional parameter "pageToken": The value returned
// by the last `ListBudgetsResponse` which indicates that this is a
// continuation of a prior `ListBudgets` call, and that the system
// should return the next page of data.
func (c *BillingAccountsBudgetsListCall) PageToken(pageToken string) *BillingAccountsBudgetsListCall {
	c.urlParams_.Set("pageToken", pageToken)
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
// for more information.
func (c *BillingAccountsBudgetsListCall) Fields(s ...googleapi.Field) *BillingAccountsBudgetsListCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets the optional parameter which makes the operation
// fail if the object's ETag matches the given value. This is useful for
// getting updates only after the object has changed since the last
// request. Use googleapi.IsNotModified to check whether the response
// error from Do is the result of In-None-Match.
func (c *BillingAccountsBudgetsListCall) IfNoneMatch(entityTag string) *BillingAccountsBudgetsListCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method. Any
// pending HTTP request will be aborted if the provided context is
// canceled.
func (c *BillingAccountsBudgetsListCall) Context(ctx context.Context) *BillingAccountsBudgetsListCall {
	c.ctx_ = ctx
	return c
}

// Header returns an http.Header that can be modified by the caller to
// add HTTP headers to the request.
func (c *BillingAccountsBudgetsListCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *BillingAccountsBudgetsListCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := make(http.Header)
	reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200902")
	for k, v := range c.header_ {
		reqHeaders[k] = v
	}
	reqHeaders.Set("User-Agent", c.s.userAgent())
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	var body io.Reader = nil
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1beta1/{+parent}/budgets")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "billingbudgets.billingAccounts.budgets.list" call.
// Exactly one of *GoogleCloudBillingBudgetsV1beta1ListBudgetsResponse
// or error will be non-nil. Any non-2xx status code is an error.
// Response headers are in either
// *GoogleCloudBillingBudgetsV1beta1ListBudgetsResponse.ServerResponse.He
// ader or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was
// returned.
func (c *BillingAccountsBudgetsListCall) Do(opts ...googleapi.CallOption) (*GoogleCloudBillingBudgetsV1beta1ListBudgetsResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, &googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		}
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, err
	}
	ret := &GoogleCloudBillingBudgetsV1beta1ListBudgetsResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	if err := gensupport.DecodeResponse(target, res); err != nil {
		return nil, err
	}
	return ret, nil
	// {
	//   "description": "Returns a list of budgets for a billing account. WARNING: There are some fields exposed on the Google Cloud Console that aren't available on this API. When reading from the API, you will not see these fields in the return value, though they may have been set in the Cloud Console.",
	//   "flatPath": "v1beta1/billingAccounts/{billingAccountsId}/budgets",
	//   "httpMethod": "GET",
	//   "id": "billingbudgets.billingAccounts.budgets.list",
	//   "parameterOrder": [
	//     "parent"
	//   ],
	//   "parameters": {
	//     "pageSize": {
	//       "description": "Optional. The maximum number of budgets to return per page. The default and maximum value are 100.",
	//       "format": "int32",
	//       "location": "query",
	//       "type": "integer"
	//     },
	//     "pageToken": {
	//       "description": "Optional. The value returned by the last `ListBudgetsResponse` which indicates that this is a continuation of a prior `ListBudgets` call, and that the system should return the next page of data.",
	//       "location": "query",
	//       "type": "string"
	//     },
	//     "parent": {
	//       "description": "Required. Name of billing account to list budgets under. Values are of the form `billingAccounts/{billingAccountId}`.",
	//       "location": "path",
	//       "pattern": "^billingAccounts/[^/]+$",
	//       "required": true,
	//       "type": "string"
	//     }
	//   },
	//   "path": "v1beta1/{+parent}/budgets",
	//   "response": {
	//     "$ref": "GoogleCloudBillingBudgetsV1beta1ListBudgetsResponse"
	//   },
	//   "scopes": [
	//     "https://www.googleapis.com/auth/cloud-billing",
	//     "https://www.googleapis.com/auth/cloud-platform"
	//   ]
	// }

}

// Pages invokes f for each page of results.
// A non-nil error returned from f will halt the iteration.
// The provided context supersedes any context provided to the Context method.
func (c *BillingAccountsBudgetsListCall) Pages(ctx context.Context, f func(*GoogleCloudBillingBudgetsV1beta1ListBudgetsResponse) error) error {
	c.ctx_ = ctx
	defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point
	for {
		x, err := c.Do()
		if err != nil {
			return err
		}
		if err := f(x); err != nil {
			return err
		}
		if x.NextPageToken == "" {
			return nil
		}
		c.PageToken(x.NextPageToken)
	}
}

// method id "billingbudgets.billingAccounts.budgets.patch":

type BillingAccountsBudgetsPatchCall struct {
	s                                                   *Service
	name                                                string
	googlecloudbillingbudgetsv1beta1updatebudgetrequest *GoogleCloudBillingBudgetsV1beta1UpdateBudgetRequest
	urlParams_                                          gensupport.URLParams
	ctx_                                                context.Context
	header_                                             http.Header
}

// Patch: Updates a budget and returns the updated budget. WARNING:
// There are some fields exposed on the Google Cloud Console that aren't
// available on this API. Budget fields that are not exposed in this API
// will not be changed by this method.
func (r *BillingAccountsBudgetsService) Patch(name string, googlecloudbillingbudgetsv1beta1updatebudgetrequest *GoogleCloudBillingBudgetsV1beta1UpdateBudgetRequest) *BillingAccountsBudgetsPatchCall {
	c := &BillingAccountsBudgetsPatchCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	c.googlecloudbillingbudgetsv1beta1updatebudgetrequest = googlecloudbillingbudgetsv1beta1updatebudgetrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
// for more information.
func (c *BillingAccountsBudgetsPatchCall) Fields(s ...googleapi.Field) *BillingAccountsBudgetsPatchCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method. Any
// pending HTTP request will be aborted if the provided context is
// canceled.
func (c *BillingAccountsBudgetsPatchCall) Context(ctx context.Context) *BillingAccountsBudgetsPatchCall {
	c.ctx_ = ctx
	return c
}

// Header returns an http.Header that can be modified by the caller to
// add HTTP headers to the request.
func (c *BillingAccountsBudgetsPatchCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *BillingAccountsBudgetsPatchCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := make(http.Header)
	reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200902")
	for k, v := range c.header_ {
		reqHeaders[k] = v
	}
	reqHeaders.Set("User-Agent", c.s.userAgent())
	var body io.Reader = nil
	body, err := googleapi.WithoutDataWrapper.JSONReader(c.googlecloudbillingbudgetsv1beta1updatebudgetrequest)
	if err != nil {
		return nil, err
	}
	reqHeaders.Set("Content-Type", "application/json")
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1beta1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("PATCH", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "billingbudgets.billingAccounts.budgets.patch" call.
// Exactly one of *GoogleCloudBillingBudgetsV1beta1Budget or error will
// be non-nil. Any non-2xx status code is an error. Response headers are
// in either
// *GoogleCloudBillingBudgetsV1beta1Budget.ServerResponse.Header or (if
// a response was returned at all) in error.(*googleapi.Error).Header.
// Use googleapi.IsNotModified to check whether the returned error was
// because http.StatusNotModified was returned.
func (c *BillingAccountsBudgetsPatchCall) Do(opts ...googleapi.CallOption) (*GoogleCloudBillingBudgetsV1beta1Budget, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, &googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		}
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, err
	}
	ret := &GoogleCloudBillingBudgetsV1beta1Budget{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	if err := gensupport.DecodeResponse(target, res); err != nil {
		return nil, err
	}
	return ret, nil
	// {
	//   "description": "Updates a budget and returns the updated budget. WARNING: There are some fields exposed on the Google Cloud Console that aren't available on this API. Budget fields that are not exposed in this API will not be changed by this method.",
	//   "flatPath": "v1beta1/billingAccounts/{billingAccountsId}/budgets/{budgetsId}",
	//   "httpMethod": "PATCH",
	//   "id": "billingbudgets.billingAccounts.budgets.patch",
	//   "parameterOrder": [
	//     "name"
	//   ],
	//   "parameters": {
	//     "name": {
	//       "description": "Output only. Resource name of the budget. The resource name implies the scope of a budget. Values are of the form `billingAccounts/{billingAccountId}/budgets/{budgetId}`.",
	//       "location": "path",
	//       "pattern": "^billingAccounts/[^/]+/budgets/[^/]+$",
	//       "required": true,
	//       "type": "string"
	//     }
	//   },
	//   "path": "v1beta1/{+name}",
	//   "request": {
	//     "$ref": "GoogleCloudBillingBudgetsV1beta1UpdateBudgetRequest"
	//   },
	//   "response": {
	//     "$ref": "GoogleCloudBillingBudgetsV1beta1Budget"
	//   },
	//   "scopes": [
	//     "https://www.googleapis.com/auth/cloud-billing",
	//     "https://www.googleapis.com/auth/cloud-platform"
	//   ]
	// }

}
