// Copyright 2021 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 data

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

	gax "github.com/googleapis/gax-go/v2"
	"google.golang.org/api/option"
	"google.golang.org/api/option/internaloption"
	gtransport "google.golang.org/api/transport/grpc"
	datapb "google.golang.org/genproto/googleapis/analytics/data/v1alpha"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/metadata"
)

var newAlphaAnalyticsDataClientHook clientHook

// AlphaAnalyticsDataCallOptions contains the retry settings for each method of AlphaAnalyticsDataClient.
type AlphaAnalyticsDataCallOptions struct {
	RunReport            []gax.CallOption
	RunPivotReport       []gax.CallOption
	BatchRunReports      []gax.CallOption
	BatchRunPivotReports []gax.CallOption
	GetMetadata          []gax.CallOption
	RunRealtimeReport    []gax.CallOption
}

func defaultAlphaAnalyticsDataClientOptions() []option.ClientOption {
	return []option.ClientOption{
		internaloption.WithDefaultEndpoint("analyticsdata.googleapis.com:443"),
		internaloption.WithDefaultMTLSEndpoint("analyticsdata.mtls.googleapis.com:443"),
		internaloption.WithDefaultAudience("https://analyticsdata.googleapis.com/"),
		internaloption.WithDefaultScopes(DefaultAuthScopes()...),
		option.WithGRPCDialOption(grpc.WithDisableServiceConfig()),
		option.WithGRPCDialOption(grpc.WithDefaultCallOptions(
			grpc.MaxCallRecvMsgSize(math.MaxInt32))),
	}
}

func defaultAlphaAnalyticsDataCallOptions() *AlphaAnalyticsDataCallOptions {
	return &AlphaAnalyticsDataCallOptions{
		RunReport:            []gax.CallOption{},
		RunPivotReport:       []gax.CallOption{},
		BatchRunReports:      []gax.CallOption{},
		BatchRunPivotReports: []gax.CallOption{},
		GetMetadata: []gax.CallOption{
			gax.WithRetry(func() gax.Retryer {
				return gax.OnCodes([]codes.Code{
					codes.Unknown,
				}, gax.Backoff{
					Initial:    1000 * time.Millisecond,
					Max:        60000 * time.Millisecond,
					Multiplier: 1.30,
				})
			}),
		},
		RunRealtimeReport: []gax.CallOption{
			gax.WithRetry(func() gax.Retryer {
				return gax.OnCodes([]codes.Code{
					codes.Unknown,
				}, gax.Backoff{
					Initial:    1000 * time.Millisecond,
					Max:        60000 * time.Millisecond,
					Multiplier: 1.30,
				})
			}),
		},
	}
}

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

	// flag to opt out of default deadlines via GOOGLE_API_GO_EXPERIMENTAL_DISABLE_DEFAULT_DEADLINE
	disableDeadlines bool

	// The gRPC API client.
	alphaAnalyticsDataClient datapb.AlphaAnalyticsDataClient

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

	// The x-goog-* metadata to be sent with each request.
	xGoogMetadata metadata.MD
}

// NewAlphaAnalyticsDataClient creates a new alpha analytics data client.
//
// Google Analytics reporting data service.
func NewAlphaAnalyticsDataClient(ctx context.Context, opts ...option.ClientOption) (*AlphaAnalyticsDataClient, error) {
	clientOpts := defaultAlphaAnalyticsDataClientOptions()

	if newAlphaAnalyticsDataClientHook != nil {
		hookOpts, err := newAlphaAnalyticsDataClientHook(ctx, clientHookParams{})
		if err != nil {
			return nil, err
		}
		clientOpts = append(clientOpts, hookOpts...)
	}

	disableDeadlines, err := checkDisableDeadlines()
	if err != nil {
		return nil, err
	}

	connPool, err := gtransport.DialPool(ctx, append(clientOpts, opts...)...)
	if err != nil {
		return nil, err
	}
	c := &AlphaAnalyticsDataClient{
		connPool:         connPool,
		disableDeadlines: disableDeadlines,
		CallOptions:      defaultAlphaAnalyticsDataCallOptions(),

		alphaAnalyticsDataClient: datapb.NewAlphaAnalyticsDataClient(connPool),
	}
	c.setGoogleClientInfo()

	return c, nil
}

// Connection returns a connection to the API service.
//
// Deprecated.
func (c *AlphaAnalyticsDataClient) Connection() *grpc.ClientConn {
	return c.connPool.Conn()
}

// Close closes the connection to the API service. The user should invoke this when
// the client is no longer required.
func (c *AlphaAnalyticsDataClient) Close() error {
	return c.connPool.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 *AlphaAnalyticsDataClient) setGoogleClientInfo(keyval ...string) {
	kv := append([]string{"gl-go", versionGo()}, keyval...)
	kv = append(kv, "gapic", versionClient, "gax", gax.Version, "grpc", grpc.Version)
	c.xGoogMetadata = metadata.Pairs("x-goog-api-client", gax.XGoogHeader(kv...))
}

// RunReport returns a customized report of your Google Analytics event data. Reports
// contain statistics derived from data collected by the Google Analytics
// tracking code. The data returned from the API is as a table with columns
// for the requested dimensions and metrics. Metrics are individual
// measurements of user activity on your property, such as active users or
// event count. Dimensions break down metrics across some common criteria,
// such as country or event name.
func (c *AlphaAnalyticsDataClient) RunReport(ctx context.Context, req *datapb.RunReportRequest, opts ...gax.CallOption) (*datapb.RunReportResponse, error) {
	if _, ok := ctx.Deadline(); !ok && !c.disableDeadlines {
		cctx, cancel := context.WithTimeout(ctx, 60000*time.Millisecond)
		defer cancel()
		ctx = cctx
	}
	ctx = insertMetadata(ctx, c.xGoogMetadata)
	opts = append(c.CallOptions.RunReport[0:len(c.CallOptions.RunReport):len(c.CallOptions.RunReport)], opts...)
	var resp *datapb.RunReportResponse
	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		var err error
		resp, err = c.alphaAnalyticsDataClient.RunReport(ctx, req, settings.GRPC...)
		return err
	}, opts...)
	if err != nil {
		return nil, err
	}
	return resp, nil
}

// RunPivotReport returns a customized pivot report of your Google Analytics event data.
// Pivot reports are more advanced and expressive formats than regular
// reports. In a pivot report, dimensions are only visible if they are
// included in a pivot. Multiple pivots can be specified to further dissect
// your data.
func (c *AlphaAnalyticsDataClient) RunPivotReport(ctx context.Context, req *datapb.RunPivotReportRequest, opts ...gax.CallOption) (*datapb.RunPivotReportResponse, error) {
	if _, ok := ctx.Deadline(); !ok && !c.disableDeadlines {
		cctx, cancel := context.WithTimeout(ctx, 60000*time.Millisecond)
		defer cancel()
		ctx = cctx
	}
	ctx = insertMetadata(ctx, c.xGoogMetadata)
	opts = append(c.CallOptions.RunPivotReport[0:len(c.CallOptions.RunPivotReport):len(c.CallOptions.RunPivotReport)], opts...)
	var resp *datapb.RunPivotReportResponse
	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		var err error
		resp, err = c.alphaAnalyticsDataClient.RunPivotReport(ctx, req, settings.GRPC...)
		return err
	}, opts...)
	if err != nil {
		return nil, err
	}
	return resp, nil
}

// BatchRunReports returns multiple reports in a batch. All reports must be for the same
// Entity.
func (c *AlphaAnalyticsDataClient) BatchRunReports(ctx context.Context, req *datapb.BatchRunReportsRequest, opts ...gax.CallOption) (*datapb.BatchRunReportsResponse, error) {
	if _, ok := ctx.Deadline(); !ok && !c.disableDeadlines {
		cctx, cancel := context.WithTimeout(ctx, 60000*time.Millisecond)
		defer cancel()
		ctx = cctx
	}
	ctx = insertMetadata(ctx, c.xGoogMetadata)
	opts = append(c.CallOptions.BatchRunReports[0:len(c.CallOptions.BatchRunReports):len(c.CallOptions.BatchRunReports)], opts...)
	var resp *datapb.BatchRunReportsResponse
	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		var err error
		resp, err = c.alphaAnalyticsDataClient.BatchRunReports(ctx, req, settings.GRPC...)
		return err
	}, opts...)
	if err != nil {
		return nil, err
	}
	return resp, nil
}

// BatchRunPivotReports returns multiple pivot reports in a batch. All reports must be for the same
// Entity.
func (c *AlphaAnalyticsDataClient) BatchRunPivotReports(ctx context.Context, req *datapb.BatchRunPivotReportsRequest, opts ...gax.CallOption) (*datapb.BatchRunPivotReportsResponse, error) {
	if _, ok := ctx.Deadline(); !ok && !c.disableDeadlines {
		cctx, cancel := context.WithTimeout(ctx, 60000*time.Millisecond)
		defer cancel()
		ctx = cctx
	}
	ctx = insertMetadata(ctx, c.xGoogMetadata)
	opts = append(c.CallOptions.BatchRunPivotReports[0:len(c.CallOptions.BatchRunPivotReports):len(c.CallOptions.BatchRunPivotReports)], opts...)
	var resp *datapb.BatchRunPivotReportsResponse
	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		var err error
		resp, err = c.alphaAnalyticsDataClient.BatchRunPivotReports(ctx, req, settings.GRPC...)
		return err
	}, opts...)
	if err != nil {
		return nil, err
	}
	return resp, nil
}

// GetMetadata returns metadata for dimensions and metrics available in reporting methods.
// Used to explore the dimensions and metrics. In this method, a Google
// Analytics GA4 Property Identifier is specified in the request, and
// the metadata response includes Custom dimensions and metrics as well as
// Universal metadata.
//
// For example if a custom metric with parameter name levels_unlocked is
// registered to a property, the Metadata response will contain
// customEvent:levels_unlocked. Universal metadata are dimensions and
// metrics applicable to any property such as country and totalUsers.
func (c *AlphaAnalyticsDataClient) GetMetadata(ctx context.Context, req *datapb.GetMetadataRequest, opts ...gax.CallOption) (*datapb.Metadata, error) {
	if _, ok := ctx.Deadline(); !ok && !c.disableDeadlines {
		cctx, cancel := context.WithTimeout(ctx, 60000*time.Millisecond)
		defer cancel()
		ctx = cctx
	}
	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName())))
	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
	opts = append(c.CallOptions.GetMetadata[0:len(c.CallOptions.GetMetadata):len(c.CallOptions.GetMetadata)], opts...)
	var resp *datapb.Metadata
	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		var err error
		resp, err = c.alphaAnalyticsDataClient.GetMetadata(ctx, req, settings.GRPC...)
		return err
	}, opts...)
	if err != nil {
		return nil, err
	}
	return resp, nil
}

// RunRealtimeReport the Google Analytics Realtime API returns a customized report of realtime
// event data for your property. These reports show events and usage from the
// last 30 minutes.
func (c *AlphaAnalyticsDataClient) RunRealtimeReport(ctx context.Context, req *datapb.RunRealtimeReportRequest, opts ...gax.CallOption) (*datapb.RunRealtimeReportResponse, error) {
	if _, ok := ctx.Deadline(); !ok && !c.disableDeadlines {
		cctx, cancel := context.WithTimeout(ctx, 60000*time.Millisecond)
		defer cancel()
		ctx = cctx
	}
	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "property", url.QueryEscape(req.GetProperty())))
	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
	opts = append(c.CallOptions.RunRealtimeReport[0:len(c.CallOptions.RunRealtimeReport):len(c.CallOptions.RunRealtimeReport)], opts...)
	var resp *datapb.RunRealtimeReportResponse
	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		var err error
		resp, err = c.alphaAnalyticsDataClient.RunRealtimeReport(ctx, req, settings.GRPC...)
		return err
	}, opts...)
	if err != nil {
		return nil, err
	}
	return resp, nil
}
