// Copyright 2020 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 gapic-generator. DO NOT EDIT.

package expr

import (
	"context"
	"math"

	gax "github.com/googleapis/gax-go/v2"
	"google.golang.org/api/option"
	"google.golang.org/api/transport"
	exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
	"google.golang.org/grpc"
	"google.golang.org/grpc/metadata"
)

// ConformanceCallOptions contains the retry settings for each method of ConformanceClient.
type ConformanceCallOptions struct {
	Parse []gax.CallOption
	Check []gax.CallOption
	Eval  []gax.CallOption
}

func defaultConformanceClientOptions() []option.ClientOption {
	return []option.ClientOption{
		option.WithEndpoint("cel.googleapis.com:443"),
		option.WithScopes(DefaultAuthScopes()...),
		option.WithGRPCDialOption(grpc.WithDefaultCallOptions(
			grpc.MaxCallRecvMsgSize(math.MaxInt32))),
	}
}

func defaultConformanceCallOptions() *ConformanceCallOptions {
	retry := map[[2]string][]gax.CallOption{}
	return &ConformanceCallOptions{
		Parse: retry[[2]string{"default", "non_idempotent"}],
		Check: retry[[2]string{"default", "non_idempotent"}],
		Eval:  retry[[2]string{"default", "non_idempotent"}],
	}
}

// ConformanceClient is a client for interacting with Common Expression Language.
//
// Methods, except Close, may be called concurrently. However, fields must not be modified concurrently with method calls.
type ConformanceClient struct {
	// The connection to the service.
	conn *grpc.ClientConn

	// The gRPC API client.
	conformanceClient exprpb.ConformanceServiceClient

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

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

// NewConformanceClient creates a new conformance service client.
//
// Access a CEL implementation from another process or machine.
// A CEL implementation is decomposed as a parser, a static checker,
// and an evaluator.  Every CEL implementation is expected to provide
// a server for this API.  The API will be used for conformance testing
// and other utilities.
func NewConformanceClient(ctx context.Context, opts ...option.ClientOption) (*ConformanceClient, error) {
	conn, err := transport.DialGRPC(ctx, append(defaultConformanceClientOptions(), opts...)...)
	if err != nil {
		return nil, err
	}
	c := &ConformanceClient{
		conn:        conn,
		CallOptions: defaultConformanceCallOptions(),

		conformanceClient: exprpb.NewConformanceServiceClient(conn),
	}
	c.setGoogleClientInfo()
	return c, nil
}

// Connection returns the client's connection to the API service.
func (c *ConformanceClient) Connection() *grpc.ClientConn {
	return c.conn
}

// Close closes the connection to the API service. The user should invoke this when
// the client is no longer required.
func (c *ConformanceClient) Close() error {
	return c.conn.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 *ConformanceClient) 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...))
}

// Parse transforms CEL source text into a parsed representation.
func (c *ConformanceClient) Parse(ctx context.Context, req *exprpb.ParseRequest, opts ...gax.CallOption) (*exprpb.ParseResponse, error) {
	ctx = insertMetadata(ctx, c.xGoogMetadata)
	opts = append(c.CallOptions.Parse[0:len(c.CallOptions.Parse):len(c.CallOptions.Parse)], opts...)
	var resp *exprpb.ParseResponse
	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		var err error
		resp, err = c.conformanceClient.Parse(ctx, req, settings.GRPC...)
		return err
	}, opts...)
	if err != nil {
		return nil, err
	}
	return resp, nil
}

// Check runs static checks on a parsed CEL representation and return
// an annotated representation, or a set of issues.
func (c *ConformanceClient) Check(ctx context.Context, req *exprpb.CheckRequest, opts ...gax.CallOption) (*exprpb.CheckResponse, error) {
	ctx = insertMetadata(ctx, c.xGoogMetadata)
	opts = append(c.CallOptions.Check[0:len(c.CallOptions.Check):len(c.CallOptions.Check)], opts...)
	var resp *exprpb.CheckResponse
	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		var err error
		resp, err = c.conformanceClient.Check(ctx, req, settings.GRPC...)
		return err
	}, opts...)
	if err != nil {
		return nil, err
	}
	return resp, nil
}

// Eval evaluates a parsed or annotation CEL representation given
// values of external bindings.
func (c *ConformanceClient) Eval(ctx context.Context, req *exprpb.EvalRequest, opts ...gax.CallOption) (*exprpb.EvalResponse, error) {
	ctx = insertMetadata(ctx, c.xGoogMetadata)
	opts = append(c.CallOptions.Eval[0:len(c.CallOptions.Eval):len(c.CallOptions.Eval)], opts...)
	var resp *exprpb.EvalResponse
	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		var err error
		resp, err = c.conformanceClient.Eval(ctx, req, settings.GRPC...)
		return err
	}, opts...)
	if err != nil {
		return nil, err
	}
	return resp, nil
}
