// 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 chromeuxreport provides access to the Chrome UX Report API.
//
// For product documentation, see: https://developers.google.com/web/tools/chrome-user-experience-report/api/reference
//
// Creating a client
//
// Usage example:
//
//   import "google.golang.org/api/chromeuxreport/v1"
//   ...
//   ctx := context.Background()
//   chromeuxreportService, err := chromeuxreport.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
//
// To use an API key for authentication (note: some APIs do not support API keys), use option.WithAPIKey:
//
//   chromeuxreportService, err := chromeuxreport.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, ...)
//   chromeuxreportService, err := chromeuxreport.NewService(ctx, option.WithTokenSource(config.TokenSource(ctx, token)))
//
// See https://godoc.org/google.golang.org/api/option/ for details on options.
package chromeuxreport // import "google.golang.org/api/chromeuxreport/v1"

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 = "chromeuxreport:v1"
const apiName = "chromeuxreport"
const apiVersion = "v1"
const basePath = "https://chromeuxreport.googleapis.com/"
const mtlsBasePath = "https://chromeuxreport.mtls.googleapis.com/"

// NewService creates a new Service.
func NewService(ctx context.Context, opts ...option.ClientOption) (*Service, error) {
	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.Records = NewRecordsService(s)
	return s, nil
}

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

	Records *RecordsService
}

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

func NewRecordsService(s *Service) *RecordsService {
	rs := &RecordsService{s: s}
	return rs
}

type RecordsService struct {
	s *Service
}

// Bin: A bin is a discrete portion of data spanning from start to end,
// or if no end is given, then from start to +inf. A bin's start and end
// values are given in the value type of the metric it represents. For
// example, "first contentful paint" is measured in milliseconds and
// exposed as ints, therefore its metric bins will use int32s for its
// start and end types. However, "cumulative layout shift" is measured
// in unitless decimals and is exposed as a decimal encoded as a string,
// therefore its metric bins will use strings for its value type.
type Bin struct {
	// Density: The proportion of users that experienced this bin's value
	// for the given metric.
	Density float64 `json:"density,omitempty"`

	// End: End is the end of the data bin. If end is not populated, then
	// the bin has no end and is valid from start to +inf.
	End interface{} `json:"end,omitempty"`

	// Start: Start is the beginning of the data bin.
	Start interface{} `json:"start,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Density") 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. "Density") 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 *Bin) MarshalJSON() ([]byte, error) {
	type NoMethod Bin
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

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

// Key: Key defines all the dimensions that identify this record as
// unique.
type Key struct {
	// EffectiveConnectionType: The effective connection type is the general
	// connection class that all users experienced for this record. This
	// field uses the values ["offline", "slow-2G", "2G", "3G", "4G"] as
	// specified in:
	// https://wicg.github.io/netinfo/#effective-connection-types If the
	// effective connection type is unspecified, then aggregated data over
	// all effective connection types will be returned.
	EffectiveConnectionType string `json:"effectiveConnectionType,omitempty"`

	// FormFactor: The form factor is the device class that all users used
	// to access the site for this record. If the form factor is
	// unspecified, then aggregated data over all form factors will be
	// returned.
	//
	// Possible values:
	//   "ALL_FORM_FACTORS" - The default value, representing all device
	// classes.
	//   "PHONE" - The device class representing a "mobile"/"phone" sized
	// client.
	//   "DESKTOP" - The device class representing a "desktop"/"laptop" type
	// full size client.
	//   "TABLET" - The device class representing a "tablet" type client.
	FormFactor string `json:"formFactor,omitempty"`

	// Origin: Origin specifies the origin that this record is for. Note:
	// When specifying an origin, data for loads under this origin over all
	// pages are aggregated into origin level user experience data.
	Origin string `json:"origin,omitempty"`

	// Url: Url specifies a specific url that this record is for. Note: When
	// specifying a "url" only data for that specific url will be
	// aggregated.
	Url string `json:"url,omitempty"`

	// ForceSendFields is a list of field names (e.g.
	// "EffectiveConnectionType") 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. "EffectiveConnectionType")
	// 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 *Key) MarshalJSON() ([]byte, error) {
	type NoMethod Key
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// Metric: A `metric` is a set of user experience data for a single web
// performance metric, like "first contentful paint". It contains a
// summary histogram of real world Chrome usage as a series of `bins`.
type Metric struct {
	// Histogram: The histogram of user experiences for a metric. The
	// histogram will have at least one bin and the densities of all bins
	// will add up to ~1.
	Histogram []*Bin `json:"histogram,omitempty"`

	// Percentiles: Common useful percentiles of the Metric. The value type
	// for the percentiles will be the same as the value types given for the
	// Histogram bins.
	Percentiles *Percentiles `json:"percentiles,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Histogram") 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. "Histogram") 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 *Metric) MarshalJSON() ([]byte, error) {
	type NoMethod Metric
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// Percentiles: Percentiles contains synthetic values of a metric at a
// given statistical percentile. These are used for estimating a
// metric's value as experienced by a percentage of users out of the
// total number of users.
type Percentiles struct {
	// P75: 75% of users experienced the given metric at or below this
	// value.
	P75 interface{} `json:"p75,omitempty"`

	// ForceSendFields is a list of field names (e.g. "P75") 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. "P75") 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 *Percentiles) MarshalJSON() ([]byte, error) {
	type NoMethod Percentiles
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// QueryRequest: Request payload sent by a physical web client. This
// request includes all necessary context to load a particular user
// experience record.
type QueryRequest struct {
	// EffectiveConnectionType: The effective connection type is a query
	// dimension that specifies the effective network class that the
	// record's data should belong to. This field uses the values
	// ["offline", "slow-2G", "2G", "3G", "4G"] as specified in:
	// https://wicg.github.io/netinfo/#effective-connection-types Note: If
	// no effective connection type is specified, then a special record with
	// aggregated data over all effective connection types will be returned.
	EffectiveConnectionType string `json:"effectiveConnectionType,omitempty"`

	// FormFactor: The form factor is a query dimension that specifies the
	// device class that the record's data should belong to. Note: If no
	// form factor is specified, then a special record with aggregated data
	// over all form factors will be returned.
	//
	// Possible values:
	//   "ALL_FORM_FACTORS" - The default value, representing all device
	// classes.
	//   "PHONE" - The device class representing a "mobile"/"phone" sized
	// client.
	//   "DESKTOP" - The device class representing a "desktop"/"laptop" type
	// full size client.
	//   "TABLET" - The device class representing a "tablet" type client.
	FormFactor string `json:"formFactor,omitempty"`

	// Metrics: The metrics that should be included in the response. If none
	// are specified then any metrics found will be returned. Allowed
	// values: ["first_contentful_paint", "first_input_delay",
	// "largest_contentful_paint", "cumulative_layout_shift"]
	Metrics []string `json:"metrics,omitempty"`

	// Origin: The url pattern "origin" refers to a url pattern that is the
	// origin of a website. Examples: "https://example.com",
	// "https://cloud.google.com"
	Origin string `json:"origin,omitempty"`

	// Url: The url pattern "url" refers to a url pattern that is any
	// arbitrary url. Examples: "https://example.com/",
	// "https://cloud.google.com/why-google-cloud/"
	Url string `json:"url,omitempty"`

	// ForceSendFields is a list of field names (e.g.
	// "EffectiveConnectionType") 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. "EffectiveConnectionType")
	// 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 *QueryRequest) MarshalJSON() ([]byte, error) {
	type NoMethod QueryRequest
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// QueryResponse: Response payload sent back to a physical web client.
// This response contains the record found based on the identiers
// present in a `QueryRequest`. The returned response will have a
// record, and sometimes details on normalization actions taken on the
// request that were necessary to make the request successful.
type QueryResponse struct {
	// Record: The record that was found.
	Record *Record `json:"record,omitempty"`

	// UrlNormalizationDetails: These are details about automated
	// normalization actions that were taken in order to make the requested
	// `url_pattern` valid.
	UrlNormalizationDetails *UrlNormalization `json:"urlNormalizationDetails,omitempty"`

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

	// ForceSendFields is a list of field names (e.g. "Record") 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. "Record") 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 *QueryResponse) MarshalJSON() ([]byte, error) {
	type NoMethod QueryResponse
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// Record: Record is a single Chrome UX report data record. It contains
// use experience statistics for a single url pattern and set of
// dimensions.
type Record struct {
	// Key: Key defines all of the unique querying parameters needed to look
	// up a user experience record.
	Key *Key `json:"key,omitempty"`

	// Metrics: Metrics is the map of user experience data available for the
	// record defined in the key field. Metrics are keyed on the metric
	// name. Allowed key values: ["first_contentful_paint",
	// "first_input_delay", "largest_contentful_paint",
	// "cumulative_layout_shift"]
	Metrics map[string]Metric `json:"metrics,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Key") 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. "Key") 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 *Record) MarshalJSON() ([]byte, error) {
	type NoMethod Record
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// UrlNormalization: Object representing the normalization actions taken
// to normalize a url to achieve a higher chance of successful lookup.
// These are simple automated changes that are taken when looking up the
// provided `url_patten` would be known to fail. Complex actions like
// following redirects are not handled.
type UrlNormalization struct {
	// NormalizedUrl: The URL after any normalization actions. This is a
	// valid user experience URL that could reasonably be looked up.
	NormalizedUrl string `json:"normalizedUrl,omitempty"`

	// OriginalUrl: The original requested URL prior to any normalization
	// actions.
	OriginalUrl string `json:"originalUrl,omitempty"`

	// ForceSendFields is a list of field names (e.g. "NormalizedUrl") 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. "NormalizedUrl") 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 *UrlNormalization) MarshalJSON() ([]byte, error) {
	type NoMethod UrlNormalization
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// method id "chromeuxreport.records.queryRecord":

type RecordsQueryRecordCall struct {
	s            *Service
	queryrequest *QueryRequest
	urlParams_   gensupport.URLParams
	ctx_         context.Context
	header_      http.Header
}

// QueryRecord: Queries the Chrome User Experience for a single `record`
// for a given site. Returns a `record` that contains one or more
// `metrics` corresponding to performance data about the requested site.
func (r *RecordsService) QueryRecord(queryrequest *QueryRequest) *RecordsQueryRecordCall {
	c := &RecordsQueryRecordCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.queryrequest = queryrequest
	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 *RecordsQueryRecordCall) Fields(s ...googleapi.Field) *RecordsQueryRecordCall {
	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 *RecordsQueryRecordCall) Context(ctx context.Context) *RecordsQueryRecordCall {
	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 *RecordsQueryRecordCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *RecordsQueryRecordCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := make(http.Header)
	reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200925")
	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.queryrequest)
	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, "v1/records:queryRecord")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "chromeuxreport.records.queryRecord" call.
// Exactly one of *QueryResponse or error will be non-nil. Any non-2xx
// status code is an error. Response headers are in either
// *QueryResponse.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 *RecordsQueryRecordCall) Do(opts ...googleapi.CallOption) (*QueryResponse, 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 := &QueryResponse{
		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": "Queries the Chrome User Experience for a single `record` for a given site. Returns a `record` that contains one or more `metrics` corresponding to performance data about the requested site.",
	//   "flatPath": "v1/records:queryRecord",
	//   "httpMethod": "POST",
	//   "id": "chromeuxreport.records.queryRecord",
	//   "parameterOrder": [],
	//   "parameters": {},
	//   "path": "v1/records:queryRecord",
	//   "request": {
	//     "$ref": "QueryRequest"
	//   },
	//   "response": {
	//     "$ref": "QueryResponse"
	//   }
	// }

}
