// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://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.

// This file was generated by protoveneer. DO NOT EDIT.

package genai

import (
	"fmt"
	"time"

	pb "cloud.google.com/go/ai/generativelanguage/apiv1beta/generativelanguagepb"
	"github.com/googleapis/gax-go/v2/apierror"
	spb "google.golang.org/genproto/googleapis/rpc/status"
	gstatus "google.golang.org/grpc/status"
	"google.golang.org/protobuf/types/known/durationpb"
	"google.golang.org/protobuf/types/known/structpb"
	"google.golang.org/protobuf/types/known/timestamppb"
)

// BatchEmbedContentsResponse is the response to a `BatchEmbedContentsRequest`.
type BatchEmbedContentsResponse struct {
	// Output only. The embeddings for each request, in the same order as provided
	// in the batch request.
	Embeddings []*ContentEmbedding
}

func (v *BatchEmbedContentsResponse) toProto() *pb.BatchEmbedContentsResponse {
	if v == nil {
		return nil
	}
	return &pb.BatchEmbedContentsResponse{
		Embeddings: pvTransformSlice(v.Embeddings, (*ContentEmbedding).toProto),
	}
}

func (BatchEmbedContentsResponse) fromProto(p *pb.BatchEmbedContentsResponse) *BatchEmbedContentsResponse {
	if p == nil {
		return nil
	}
	return &BatchEmbedContentsResponse{
		Embeddings: pvTransformSlice(p.Embeddings, (ContentEmbedding{}).fromProto),
	}
}

// Blob contains raw media bytes.
//
// Text should not be sent as raw bytes, use the 'text' field.
type Blob struct {
	// The IANA standard MIME type of the source data.
	// Examples:
	//   - image/png
	//   - image/jpeg
	//
	// If an unsupported MIME type is provided, an error will be returned. For a
	// complete list of supported types, see [Supported file
	// formats](https://ai.google.dev/gemini-api/docs/prompting_with_media#supported_file_formats).
	MIMEType string
	// Raw bytes for media formats.
	Data []byte
}

func (v *Blob) toProto() *pb.Blob {
	if v == nil {
		return nil
	}
	return &pb.Blob{
		MimeType: v.MIMEType,
		Data:     v.Data,
	}
}

func (Blob) fromProto(p *pb.Blob) *Blob {
	if p == nil {
		return nil
	}
	return &Blob{
		MIMEType: p.MimeType,
		Data:     p.Data,
	}
}

// BlockReason is specifies what was the reason why prompt was blocked.
type BlockReason int32

const (
	// BlockReasonUnspecified means default value. This value is unused.
	BlockReasonUnspecified BlockReason = 0
	// BlockReasonSafety means prompt was blocked due to safety reasons. You can inspect
	// `safety_ratings` to understand which safety category blocked it.
	BlockReasonSafety BlockReason = 1
	// BlockReasonOther means prompt was blocked due to unknown reasons.
	BlockReasonOther BlockReason = 2
)

var namesForBlockReason = map[BlockReason]string{
	BlockReasonUnspecified: "BlockReasonUnspecified",
	BlockReasonSafety:      "BlockReasonSafety",
	BlockReasonOther:       "BlockReasonOther",
}

func (v BlockReason) String() string {
	if n, ok := namesForBlockReason[v]; ok {
		return n
	}
	return fmt.Sprintf("BlockReason(%d)", v)
}

// CachedContent is content that has been preprocessed and can be used in subsequent request
// to GenerativeService.
//
// Cached content can be only used with model it was created for.
type CachedContent struct {
	// Specifies when this resource will expire.
	//
	// Types that are assignable to Expiration:
	//
	//	*CachedContent_ExpireTime
	//	*CachedContent_Ttl
	Expiration ExpireTimeOrTTL
	// Optional. Identifier. The resource name referring to the cached content.
	// Format: `cachedContents/{id}`
	Name string
	// Optional. Immutable. The user-generated meaningful display name of the
	// cached content. Maximum 128 Unicode characters.
	DisplayName string
	// Required. Immutable. The name of the `Model` to use for cached content
	// Format: `models/{model}`
	Model string
	// Optional. Input only. Immutable. Developer set system instruction.
	// Currently text only.
	SystemInstruction *Content
	// Optional. Input only. Immutable. The content to cache.
	Contents []*Content
	// Optional. Input only. Immutable. A list of `Tools` the model may use to
	// generate the next response
	Tools []*Tool
	// Optional. Input only. Immutable. Tool config. This config is shared for all
	// tools.
	ToolConfig *ToolConfig
	// Output only. Creation time of the cache entry.
	CreateTime time.Time
	// Output only. When the cache entry was last updated in UTC time.
	UpdateTime time.Time
	// Output only. Metadata on the usage of the cached content.
	UsageMetadata *CachedContentUsageMetadata
}

func (v *CachedContent) toProto() *pb.CachedContent {
	if v == nil {
		return nil
	}
	p := &pb.CachedContent{
		Name:              pvAddrOrNil(v.Name),
		DisplayName:       pvAddrOrNil(v.DisplayName),
		Model:             pvAddrOrNil(v.Model),
		SystemInstruction: v.SystemInstruction.toProto(),
		Contents:          pvTransformSlice(v.Contents, (*Content).toProto),
		Tools:             pvTransformSlice(v.Tools, (*Tool).toProto),
		ToolConfig:        v.ToolConfig.toProto(),
		CreateTime:        pvTimeToProto(v.CreateTime),
		UpdateTime:        pvTimeToProto(v.UpdateTime),
		UsageMetadata:     v.UsageMetadata.toProto(),
	}
	populateCachedContentTo(p, v)
	return p
}

func (CachedContent) fromProto(p *pb.CachedContent) *CachedContent {
	if p == nil {
		return nil
	}
	v := &CachedContent{
		Name:              pvDerefOrZero(p.Name),
		DisplayName:       pvDerefOrZero(p.DisplayName),
		Model:             pvDerefOrZero(p.Model),
		SystemInstruction: (Content{}).fromProto(p.SystemInstruction),
		Contents:          pvTransformSlice(p.Contents, (Content{}).fromProto),
		Tools:             pvTransformSlice(p.Tools, (Tool{}).fromProto),
		ToolConfig:        (ToolConfig{}).fromProto(p.ToolConfig),
		CreateTime:        pvTimeFromProto(p.CreateTime),
		UpdateTime:        pvTimeFromProto(p.UpdateTime),
		UsageMetadata:     (CachedContentUsageMetadata{}).fromProto(p.UsageMetadata),
	}
	populateCachedContentFrom(v, p)
	return v
}

// CachedContentUsageMetadata is metadata on the usage of the cached content.
type CachedContentUsageMetadata struct {
	// Total number of tokens that the cached content consumes.
	TotalTokenCount int32
}

func (v *CachedContentUsageMetadata) toProto() *pb.CachedContent_UsageMetadata {
	if v == nil {
		return nil
	}
	return &pb.CachedContent_UsageMetadata{
		TotalTokenCount: v.TotalTokenCount,
	}
}

func (CachedContentUsageMetadata) fromProto(p *pb.CachedContent_UsageMetadata) *CachedContentUsageMetadata {
	if p == nil {
		return nil
	}
	return &CachedContentUsageMetadata{
		TotalTokenCount: p.TotalTokenCount,
	}
}

// Candidate is a response candidate generated from the model.
type Candidate struct {
	// Output only. Index of the candidate in the list of candidates.
	Index int32
	// Output only. Generated content returned from the model.
	Content *Content
	// Optional. Output only. The reason why the model stopped generating tokens.
	//
	// If empty, the model has not stopped generating the tokens.
	FinishReason FinishReason
	// List of ratings for the safety of a response candidate.
	//
	// There is at most one rating per category.
	SafetyRatings []*SafetyRating
	// Output only. Citation information for model-generated candidate.
	//
	// This field may be populated with recitation information for any text
	// included in the `content`. These are passages that are "recited" from
	// copyrighted material in the foundational LLM's training data.
	CitationMetadata *CitationMetadata
	// Output only. Token count for this candidate.
	TokenCount int32
}

func (v *Candidate) toProto() *pb.Candidate {
	if v == nil {
		return nil
	}
	return &pb.Candidate{
		Index:            pvAddrOrNil(v.Index),
		Content:          v.Content.toProto(),
		FinishReason:     pb.Candidate_FinishReason(v.FinishReason),
		SafetyRatings:    pvTransformSlice(v.SafetyRatings, (*SafetyRating).toProto),
		CitationMetadata: v.CitationMetadata.toProto(),
		TokenCount:       v.TokenCount,
	}
}

func (Candidate) fromProto(p *pb.Candidate) *Candidate {
	if p == nil {
		return nil
	}
	return &Candidate{
		Index:            pvDerefOrZero(p.Index),
		Content:          (Content{}).fromProto(p.Content),
		FinishReason:     FinishReason(p.FinishReason),
		SafetyRatings:    pvTransformSlice(p.SafetyRatings, (SafetyRating{}).fromProto),
		CitationMetadata: (CitationMetadata{}).fromProto(p.CitationMetadata),
		TokenCount:       p.TokenCount,
	}
}

// CitationMetadata is a collection of source attributions for a piece of content.
type CitationMetadata struct {
	// Citations to sources for a specific response.
	CitationSources []*CitationSource
}

func (v *CitationMetadata) toProto() *pb.CitationMetadata {
	if v == nil {
		return nil
	}
	return &pb.CitationMetadata{
		CitationSources: pvTransformSlice(v.CitationSources, (*CitationSource).toProto),
	}
}

func (CitationMetadata) fromProto(p *pb.CitationMetadata) *CitationMetadata {
	if p == nil {
		return nil
	}
	return &CitationMetadata{
		CitationSources: pvTransformSlice(p.CitationSources, (CitationSource{}).fromProto),
	}
}

// CitationSource contains a citation to a source for a portion of a specific response.
type CitationSource struct {
	// Optional. Start of segment of the response that is attributed to this
	// source.
	//
	// Index indicates the start of the segment, measured in bytes.
	StartIndex *int32
	// Optional. End of the attributed segment, exclusive.
	EndIndex *int32
	// Optional. URI that is attributed as a source for a portion of the text.
	URI *string
	// Optional. License for the GitHub project that is attributed as a source for
	// segment.
	//
	// License info is required for code citations.
	License string
}

func (v *CitationSource) toProto() *pb.CitationSource {
	if v == nil {
		return nil
	}
	return &pb.CitationSource{
		StartIndex: v.StartIndex,
		EndIndex:   v.EndIndex,
		Uri:        v.URI,
		License:    pvAddrOrNil(v.License),
	}
}

func (CitationSource) fromProto(p *pb.CitationSource) *CitationSource {
	if p == nil {
		return nil
	}
	return &CitationSource{
		StartIndex: p.StartIndex,
		EndIndex:   p.EndIndex,
		URI:        p.Uri,
		License:    pvDerefOrZero(p.License),
	}
}

// CodeExecution is tool that executes code generated by the model, and automatically returns
// the result to the model.
//
// See also `ExecutableCode` and `CodeExecutionResult` which are only generated
// when using this tool.
type CodeExecution struct {
}

func (v *CodeExecution) toProto() *pb.CodeExecution {
	if v == nil {
		return nil
	}
	return &pb.CodeExecution{}
}

func (CodeExecution) fromProto(p *pb.CodeExecution) *CodeExecution {
	if p == nil {
		return nil
	}
	return &CodeExecution{}
}

// CodeExecutionResult is result of executing the `ExecutableCode`.
//
// Only generated when using the `CodeExecution`, and always follows a `part`
// containing the `ExecutableCode`.
type CodeExecutionResult struct {
	// Required. Outcome of the code execution.
	Outcome CodeExecutionResultOutcome
	// Optional. Contains stdout when code execution is successful, stderr or
	// other description otherwise.
	Output string
}

func (v *CodeExecutionResult) toProto() *pb.CodeExecutionResult {
	if v == nil {
		return nil
	}
	return &pb.CodeExecutionResult{
		Outcome: pb.CodeExecutionResult_Outcome(v.Outcome),
		Output:  v.Output,
	}
}

func (CodeExecutionResult) fromProto(p *pb.CodeExecutionResult) *CodeExecutionResult {
	if p == nil {
		return nil
	}
	return &CodeExecutionResult{
		Outcome: CodeExecutionResultOutcome(p.Outcome),
		Output:  p.Output,
	}
}

// CodeExecutionResultOutcome is enumeration of possible outcomes of the code execution.
type CodeExecutionResultOutcome int32

const (
	// CodeExecutionResultOutcomeUnspecified means unspecified status. This value should not be used.
	CodeExecutionResultOutcomeUnspecified CodeExecutionResultOutcome = 0
	// CodeExecutionResultOutcomeOK means code execution completed successfully.
	CodeExecutionResultOutcomeOK CodeExecutionResultOutcome = 1
	// CodeExecutionResultOutcomeFailed means code execution finished but with a failure. `stderr` should contain the
	// reason.
	CodeExecutionResultOutcomeFailed CodeExecutionResultOutcome = 2
	// CodeExecutionResultOutcomeDeadlineExceeded means code execution ran for too long, and was cancelled. There may or may not
	// be a partial output present.
	CodeExecutionResultOutcomeDeadlineExceeded CodeExecutionResultOutcome = 3
)

var namesForCodeExecutionResultOutcome = map[CodeExecutionResultOutcome]string{
	CodeExecutionResultOutcomeUnspecified:      "CodeExecutionResultOutcomeUnspecified",
	CodeExecutionResultOutcomeOK:               "CodeExecutionResultOutcomeOK",
	CodeExecutionResultOutcomeFailed:           "CodeExecutionResultOutcomeFailed",
	CodeExecutionResultOutcomeDeadlineExceeded: "CodeExecutionResultOutcomeDeadlineExceeded",
}

func (v CodeExecutionResultOutcome) String() string {
	if n, ok := namesForCodeExecutionResultOutcome[v]; ok {
		return n
	}
	return fmt.Sprintf("CodeExecutionResultOutcome(%d)", v)
}

// Content is the base structured datatype containing multi-part content of a message.
//
// A `Content` includes a `role` field designating the producer of the `Content`
// and a `parts` field containing multi-part data that contains the content of
// the message turn.
type Content struct {
	// Ordered `Parts` that constitute a single message. Parts may have different
	// MIME types.
	Parts []Part
	// Optional. The producer of the content. Must be either 'user' or 'model'.
	//
	// Useful to set for multi-turn conversations, otherwise can be left blank
	// or unset.
	Role string
}

func (v *Content) toProto() *pb.Content {
	if v == nil {
		return nil
	}
	return &pb.Content{
		Parts: pvTransformSlice(v.Parts, partToProto),
		Role:  v.Role,
	}
}

func (Content) fromProto(p *pb.Content) *Content {
	if p == nil {
		return nil
	}
	return &Content{
		Parts: pvTransformSlice(p.Parts, partFromProto),
		Role:  p.Role,
	}
}

// ContentEmbedding is a list of floats representing an embedding.
type ContentEmbedding struct {
	// The embedding values.
	Values []float32
}

func (v *ContentEmbedding) toProto() *pb.ContentEmbedding {
	if v == nil {
		return nil
	}
	return &pb.ContentEmbedding{
		Values: v.Values,
	}
}

func (ContentEmbedding) fromProto(p *pb.ContentEmbedding) *ContentEmbedding {
	if p == nil {
		return nil
	}
	return &ContentEmbedding{
		Values: p.Values,
	}
}

// CountTokensResponse is a response from `CountTokens`.
//
// It returns the model's `token_count` for the `prompt`.
type CountTokensResponse struct {
	// The number of tokens that the `model` tokenizes the `prompt` into.
	//
	// Always non-negative. When cached_content is set, this is still the total
	// effective prompt size. I.e. this includes the number of tokens in the
	// cached content.
	TotalTokens int32
	// Number of tokens in the cached part of the prompt, i.e. in the cached
	// content.
	CachedContentTokenCount int32
}

func (v *CountTokensResponse) toProto() *pb.CountTokensResponse {
	if v == nil {
		return nil
	}
	return &pb.CountTokensResponse{
		TotalTokens:             v.TotalTokens,
		CachedContentTokenCount: v.CachedContentTokenCount,
	}
}

func (CountTokensResponse) fromProto(p *pb.CountTokensResponse) *CountTokensResponse {
	if p == nil {
		return nil
	}
	return &CountTokensResponse{
		TotalTokens:             p.TotalTokens,
		CachedContentTokenCount: p.CachedContentTokenCount,
	}
}

// EmbedContentResponse is the response to an `EmbedContentRequest`.
type EmbedContentResponse struct {
	// Output only. The embedding generated from the input content.
	Embedding *ContentEmbedding
}

func (v *EmbedContentResponse) toProto() *pb.EmbedContentResponse {
	if v == nil {
		return nil
	}
	return &pb.EmbedContentResponse{
		Embedding: v.Embedding.toProto(),
	}
}

func (EmbedContentResponse) fromProto(p *pb.EmbedContentResponse) *EmbedContentResponse {
	if p == nil {
		return nil
	}
	return &EmbedContentResponse{
		Embedding: (ContentEmbedding{}).fromProto(p.Embedding),
	}
}

// ExecutableCode is code generated by the model that is meant to be executed, and the result
// returned to the model.
//
// Only generated when using the `CodeExecution` tool, in which the code will
// be automatically executed, and a corresponding `CodeExecutionResult` will
// also be generated.
type ExecutableCode struct {
	// Required. Programming language of the `code`.
	Language ExecutableCodeLanguage
	// Required. The code to be executed.
	Code string
}

func (v *ExecutableCode) toProto() *pb.ExecutableCode {
	if v == nil {
		return nil
	}
	return &pb.ExecutableCode{
		Language: pb.ExecutableCode_Language(v.Language),
		Code:     v.Code,
	}
}

func (ExecutableCode) fromProto(p *pb.ExecutableCode) *ExecutableCode {
	if p == nil {
		return nil
	}
	return &ExecutableCode{
		Language: ExecutableCodeLanguage(p.Language),
		Code:     p.Code,
	}
}

// ExecutableCodeLanguage is supported programming languages for the generated code.
type ExecutableCodeLanguage int32

const (
	// ExecutableCodeLanguageUnspecified means unspecified language. This value should not be used.
	ExecutableCodeLanguageUnspecified ExecutableCodeLanguage = 0
	// ExecutableCodePython means python >= 3.10, with numpy and simpy available.
	ExecutableCodePython ExecutableCodeLanguage = 1
)

var namesForExecutableCodeLanguage = map[ExecutableCodeLanguage]string{
	ExecutableCodeLanguageUnspecified: "ExecutableCodeLanguageUnspecified",
	ExecutableCodePython:              "ExecutableCodePython",
}

func (v ExecutableCodeLanguage) String() string {
	if n, ok := namesForExecutableCodeLanguage[v]; ok {
		return n
	}
	return fmt.Sprintf("ExecutableCodeLanguage(%d)", v)
}

// File is a file uploaded to the API.
type File struct {
	// Metadata for the File.
	Metadata *FileMetadata
	// Immutable. Identifier. The `File` resource name. The ID (name excluding the
	// "files/" prefix) can contain up to 40 characters that are lowercase
	// alphanumeric or dashes (-). The ID cannot start or end with a dash. If the
	// name is empty on create, a unique name will be generated. Example:
	// `files/123-456`
	Name string
	// Optional. The human-readable display name for the `File`. The display name
	// must be no more than 512 characters in length, including spaces. Example:
	// "Welcome Image"
	DisplayName string
	// Output only. MIME type of the file.
	MIMEType string
	// Output only. Size of the file in bytes.
	SizeBytes int64
	// Output only. The timestamp of when the `File` was created.
	CreateTime time.Time
	// Output only. The timestamp of when the `File` was last updated.
	UpdateTime time.Time
	// Output only. The timestamp of when the `File` will be deleted. Only set if
	// the `File` is scheduled to expire.
	ExpirationTime time.Time
	// Output only. SHA-256 hash of the uploaded bytes.
	Sha256Hash []byte
	// Output only. The uri of the `File`.
	URI string
	// Output only. Processing state of the File.
	State FileState
	// Output only. Error status if File processing failed.
	Error *apierror.APIError
}

func (v *File) toProto() *pb.File {
	if v == nil {
		return nil
	}
	p := &pb.File{
		Name:           v.Name,
		DisplayName:    v.DisplayName,
		MimeType:       v.MIMEType,
		SizeBytes:      v.SizeBytes,
		CreateTime:     pvTimeToProto(v.CreateTime),
		UpdateTime:     pvTimeToProto(v.UpdateTime),
		ExpirationTime: pvTimeToProto(v.ExpirationTime),
		Sha256Hash:     v.Sha256Hash,
		Uri:            v.URI,
		State:          pb.File_State(v.State),
		Error:          pvAPIErrorToProto(v.Error),
	}
	populateFileTo(p, v)
	return p
}

func (File) fromProto(p *pb.File) *File {
	if p == nil {
		return nil
	}
	v := &File{
		Name:           p.Name,
		DisplayName:    p.DisplayName,
		MIMEType:       p.MimeType,
		SizeBytes:      p.SizeBytes,
		CreateTime:     pvTimeFromProto(p.CreateTime),
		UpdateTime:     pvTimeFromProto(p.UpdateTime),
		ExpirationTime: pvTimeFromProto(p.ExpirationTime),
		Sha256Hash:     p.Sha256Hash,
		URI:            p.Uri,
		State:          FileState(p.State),
		Error:          pvAPIErrorFromProto(p.Error),
	}
	populateFileFrom(v, p)
	return v
}

// FileData is URI based data.
type FileData struct {
	// The IANA standard MIME type of the source data.
	// If present, this overrides the MIME type specified or inferred
	// when the file was uploaded.
	// The supported MIME types are documented on [this page].
	//
	// [this page]: https://ai.google.dev/gemini-api/docs/prompting_with_media?lang=go#supported_file_formats
	MIMEType string
	// The URI returned from UploadFile or GetFile.
	URI string
}

func (v *FileData) toProto() *pb.FileData {
	if v == nil {
		return nil
	}
	return &pb.FileData{
		MimeType: v.MIMEType,
		FileUri:  v.URI,
	}
}

func (FileData) fromProto(p *pb.FileData) *FileData {
	if p == nil {
		return nil
	}
	return &FileData{
		MIMEType: p.MimeType,
		URI:      p.FileUri,
	}
}

// FileState represents states for the lifecycle of a File.
type FileState int32

const (
	// FileStateUnspecified means the default value. This value is used if the state is omitted.
	FileStateUnspecified FileState = 0
	// FileStateProcessing means file is being processed and cannot be used for inference yet.
	FileStateProcessing FileState = 1
	// FileStateActive means file is processed and available for inference.
	FileStateActive FileState = 2
	// FileStateFailed means file failed processing.
	FileStateFailed FileState = 10
)

var namesForFileState = map[FileState]string{
	FileStateUnspecified: "FileStateUnspecified",
	FileStateProcessing:  "FileStateProcessing",
	FileStateActive:      "FileStateActive",
	FileStateFailed:      "FileStateFailed",
}

func (v FileState) String() string {
	if n, ok := namesForFileState[v]; ok {
		return n
	}
	return fmt.Sprintf("FileState(%d)", v)
}

// FinishReason is defines the reason why the model stopped generating tokens.
type FinishReason int32

const (
	// FinishReasonUnspecified means default value. This value is unused.
	FinishReasonUnspecified FinishReason = 0
	// FinishReasonStop means natural stop point of the model or provided stop sequence.
	FinishReasonStop FinishReason = 1
	// FinishReasonMaxTokens means the maximum number of tokens as specified in the request was reached.
	FinishReasonMaxTokens FinishReason = 2
	// FinishReasonSafety means the candidate content was flagged for safety reasons.
	FinishReasonSafety FinishReason = 3
	// FinishReasonRecitation means the candidate content was flagged for recitation reasons.
	FinishReasonRecitation FinishReason = 4
	// FinishReasonOther means unknown reason.
	FinishReasonOther FinishReason = 5
)

var namesForFinishReason = map[FinishReason]string{
	FinishReasonUnspecified: "FinishReasonUnspecified",
	FinishReasonStop:        "FinishReasonStop",
	FinishReasonMaxTokens:   "FinishReasonMaxTokens",
	FinishReasonSafety:      "FinishReasonSafety",
	FinishReasonRecitation:  "FinishReasonRecitation",
	FinishReasonOther:       "FinishReasonOther",
}

func (v FinishReason) String() string {
	if n, ok := namesForFinishReason[v]; ok {
		return n
	}
	return fmt.Sprintf("FinishReason(%d)", v)
}

// FunctionCall is a predicted `FunctionCall` returned from the model that contains
// a string representing the `FunctionDeclaration.name` with the
// arguments and their values.
type FunctionCall struct {
	// Required. The name of the function to call.
	// Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum
	// length of 63.
	Name string
	// Optional. The function parameters and values in JSON object format.
	Args map[string]any
}

func (v *FunctionCall) toProto() *pb.FunctionCall {
	if v == nil {
		return nil
	}
	return &pb.FunctionCall{
		Name: v.Name,
		Args: pvMapToStructPB(v.Args),
	}
}

func (FunctionCall) fromProto(p *pb.FunctionCall) *FunctionCall {
	if p == nil {
		return nil
	}
	return &FunctionCall{
		Name: p.Name,
		Args: pvMapFromStructPB(p.Args),
	}
}

// FunctionCallingConfig holds configuration for function calling.
type FunctionCallingConfig struct {
	// Optional. Specifies the mode in which function calling should execute. If
	// unspecified, the default value will be set to AUTO.
	Mode FunctionCallingMode
	// Optional. A set of function names that, when provided, limits the functions
	// the model will call.
	//
	// This should only be set when the Mode is ANY. Function names
	// should match [FunctionDeclaration.name]. With mode set to ANY, model will
	// predict a function call from the set of function names provided.
	AllowedFunctionNames []string
}

func (v *FunctionCallingConfig) toProto() *pb.FunctionCallingConfig {
	if v == nil {
		return nil
	}
	return &pb.FunctionCallingConfig{
		Mode:                 pb.FunctionCallingConfig_Mode(v.Mode),
		AllowedFunctionNames: v.AllowedFunctionNames,
	}
}

func (FunctionCallingConfig) fromProto(p *pb.FunctionCallingConfig) *FunctionCallingConfig {
	if p == nil {
		return nil
	}
	return &FunctionCallingConfig{
		Mode:                 FunctionCallingMode(p.Mode),
		AllowedFunctionNames: p.AllowedFunctionNames,
	}
}

// FunctionCallingMode is defines the execution behavior for function calling by defining the
// execution mode.
type FunctionCallingMode int32

const (
	// FunctionCallingUnspecified means unspecified function calling mode. This value should not be used.
	FunctionCallingUnspecified FunctionCallingMode = 0
	// FunctionCallingAuto means default model behavior, model decides to predict either a function call
	// or a natural language response.
	FunctionCallingAuto FunctionCallingMode = 1
	// FunctionCallingAny means model is constrained to always predicting a function call only.
	// If "allowed_function_names" are set, the predicted function call will be
	// limited to any one of "allowed_function_names", else the predicted
	// function call will be any one of the provided "function_declarations".
	FunctionCallingAny FunctionCallingMode = 2
	// FunctionCallingNone means model will not predict any function call. Model behavior is same as when
	// not passing any function declarations.
	FunctionCallingNone FunctionCallingMode = 3
)

var namesForFunctionCallingMode = map[FunctionCallingMode]string{
	FunctionCallingUnspecified: "FunctionCallingUnspecified",
	FunctionCallingAuto:        "FunctionCallingAuto",
	FunctionCallingAny:         "FunctionCallingAny",
	FunctionCallingNone:        "FunctionCallingNone",
}

func (v FunctionCallingMode) String() string {
	if n, ok := namesForFunctionCallingMode[v]; ok {
		return n
	}
	return fmt.Sprintf("FunctionCallingMode(%d)", v)
}

// FunctionDeclaration is structured representation of a function declaration as defined by the
// [OpenAPI 3.03 specification](https://spec.openapis.org/oas/v3.0.3). Included
// in this declaration are the function name and parameters. This
// FunctionDeclaration is a representation of a block of code that can be used
// as a `Tool` by the model and executed by the client.
type FunctionDeclaration struct {
	// Required. The name of the function.
	// Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum
	// length of 63.
	Name string
	// Required. A brief description of the function.
	Description string
	// Optional. Describes the parameters to this function. Reflects the Open
	// API 3.03 Parameter Object string Key: the name of the parameter. Parameter
	// names are case sensitive. Schema Value: the Schema defining the type used
	// for the parameter.
	Parameters *Schema
}

func (v *FunctionDeclaration) toProto() *pb.FunctionDeclaration {
	if v == nil {
		return nil
	}
	return &pb.FunctionDeclaration{
		Name:        v.Name,
		Description: v.Description,
		Parameters:  v.Parameters.toProto(),
	}
}

func (FunctionDeclaration) fromProto(p *pb.FunctionDeclaration) *FunctionDeclaration {
	if p == nil {
		return nil
	}
	return &FunctionDeclaration{
		Name:        p.Name,
		Description: p.Description,
		Parameters:  (Schema{}).fromProto(p.Parameters),
	}
}

// FunctionResponse is the result output from a `FunctionCall` that contains a string
// representing the `FunctionDeclaration.name` and a structured JSON
// object containing any output from the function is used as context to
// the model. This should contain the result of a`FunctionCall` made
// based on model prediction.
type FunctionResponse struct {
	// Required. The name of the function to call.
	// Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum
	// length of 63.
	Name string
	// Required. The function response in JSON object format.
	Response map[string]any
}

func (v *FunctionResponse) toProto() *pb.FunctionResponse {
	if v == nil {
		return nil
	}
	return &pb.FunctionResponse{
		Name:     v.Name,
		Response: pvMapToStructPB(v.Response),
	}
}

func (FunctionResponse) fromProto(p *pb.FunctionResponse) *FunctionResponse {
	if p == nil {
		return nil
	}
	return &FunctionResponse{
		Name:     p.Name,
		Response: pvMapFromStructPB(p.Response),
	}
}

// GenerateContentResponse is the response from a GenerateContent or GenerateContentStream call.
//
// Note on safety ratings and content filtering. They are reported for both
// prompt in `GenerateContentResponse.prompt_feedback` and for each candidate
// in `finish_reason` and in `safety_ratings`. The API contract is that:
//   - either all requested candidates are returned or no candidates at all
//   - no candidates are returned only if there was something wrong with the
//     prompt (see `prompt_feedback`)
//   - feedback on each candidate is reported on `finish_reason` and
//     `safety_ratings`.
type GenerateContentResponse struct {
	// Candidate responses from the model.
	Candidates []*Candidate
	// Returns the prompt's feedback related to the content filters.
	PromptFeedback *PromptFeedback
	// Output only. Metadata on the generation requests' token usage.
	UsageMetadata *UsageMetadata
}

func (v *GenerateContentResponse) toProto() *pb.GenerateContentResponse {
	if v == nil {
		return nil
	}
	return &pb.GenerateContentResponse{
		Candidates:     pvTransformSlice(v.Candidates, (*Candidate).toProto),
		PromptFeedback: v.PromptFeedback.toProto(),
		UsageMetadata:  v.UsageMetadata.toProto(),
	}
}

func (GenerateContentResponse) fromProto(p *pb.GenerateContentResponse) *GenerateContentResponse {
	if p == nil {
		return nil
	}
	return &GenerateContentResponse{
		Candidates:     pvTransformSlice(p.Candidates, (Candidate{}).fromProto),
		PromptFeedback: (PromptFeedback{}).fromProto(p.PromptFeedback),
		UsageMetadata:  (UsageMetadata{}).fromProto(p.UsageMetadata),
	}
}

// GenerationConfig is configuration options for model generation and outputs. Not all parameters
// may be configurable for every model.
type GenerationConfig struct {
	// Optional. Number of generated responses to return.
	//
	// Currently, this value can only be set to 1. If unset, this will default
	// to 1.
	CandidateCount *int32
	// Optional. The set of character sequences (up to 5) that will stop output
	// generation. If specified, the API will stop at the first appearance of a
	// stop sequence. The stop sequence will not be included as part of the
	// response.
	StopSequences []string
	// Optional. The maximum number of tokens to include in a candidate.
	//
	// Note: The default value varies by model, see the `Model.output_token_limit`
	// attribute of the `Model` returned from the `getModel` function.
	MaxOutputTokens *int32
	// Optional. Controls the randomness of the output.
	//
	// Note: The default value varies by model, see the `Model.temperature`
	// attribute of the `Model` returned from the `getModel` function.
	//
	// Values can range from [0.0, 2.0].
	Temperature *float32
	// Optional. The maximum cumulative probability of tokens to consider when
	// sampling.
	//
	// The model uses combined Top-k and nucleus sampling.
	//
	// Tokens are sorted based on their assigned probabilities so that only the
	// most likely tokens are considered. Top-k sampling directly limits the
	// maximum number of tokens to consider, while Nucleus sampling limits number
	// of tokens based on the cumulative probability.
	//
	// Note: The default value varies by model, see the `Model.top_p`
	// attribute of the `Model` returned from the `getModel` function.
	TopP *float32
	// Optional. The maximum number of tokens to consider when sampling.
	//
	// Models use nucleus sampling or combined Top-k and nucleus sampling.
	// Top-k sampling considers the set of `top_k` most probable tokens.
	// Models running with nucleus sampling don't allow top_k setting.
	//
	// Note: The default value varies by model, see the `Model.top_k`
	// attribute of the `Model` returned from the `getModel` function. Empty
	// `top_k` field in `Model` indicates the model doesn't apply top-k sampling
	// and doesn't allow setting `top_k` on requests.
	TopK *int32
	// Optional. Output response mimetype of the generated candidate text.
	// Supported mimetype:
	// `text/plain`: (default) Text output.
	// `application/json`: JSON response in the candidates.
	ResponseMIMEType string
	// Optional. Output response schema of the generated candidate text when
	// response mime type can have schema. Schema can be objects, primitives or
	// arrays and is a subset of [OpenAPI
	// schema](https://spec.openapis.org/oas/v3.0.3#schema).
	//
	// If set, a compatible response_mime_type must also be set.
	// Compatible mimetypes:
	// `application/json`: Schema for JSON response.
	ResponseSchema *Schema
}

func (v *GenerationConfig) toProto() *pb.GenerationConfig {
	if v == nil {
		return nil
	}
	return &pb.GenerationConfig{
		CandidateCount:   v.CandidateCount,
		StopSequences:    v.StopSequences,
		MaxOutputTokens:  v.MaxOutputTokens,
		Temperature:      v.Temperature,
		TopP:             v.TopP,
		TopK:             v.TopK,
		ResponseMimeType: v.ResponseMIMEType,
		ResponseSchema:   v.ResponseSchema.toProto(),
	}
}

func (GenerationConfig) fromProto(p *pb.GenerationConfig) *GenerationConfig {
	if p == nil {
		return nil
	}
	return &GenerationConfig{
		CandidateCount:   p.CandidateCount,
		StopSequences:    p.StopSequences,
		MaxOutputTokens:  p.MaxOutputTokens,
		Temperature:      p.Temperature,
		TopP:             p.TopP,
		TopK:             p.TopK,
		ResponseMIMEType: p.ResponseMimeType,
		ResponseSchema:   (Schema{}).fromProto(p.ResponseSchema),
	}
}

// HarmBlockThreshold specifies block at and beyond a specified harm probability.
type HarmBlockThreshold int32

const (
	// HarmBlockUnspecified means threshold is unspecified.
	HarmBlockUnspecified HarmBlockThreshold = 0
	// HarmBlockLowAndAbove means content with NEGLIGIBLE will be allowed.
	HarmBlockLowAndAbove HarmBlockThreshold = 1
	// HarmBlockMediumAndAbove means content with NEGLIGIBLE and LOW will be allowed.
	HarmBlockMediumAndAbove HarmBlockThreshold = 2
	// HarmBlockOnlyHigh means content with NEGLIGIBLE, LOW, and MEDIUM will be allowed.
	HarmBlockOnlyHigh HarmBlockThreshold = 3
	// HarmBlockNone means all content will be allowed.
	HarmBlockNone HarmBlockThreshold = 4
)

var namesForHarmBlockThreshold = map[HarmBlockThreshold]string{
	HarmBlockUnspecified:    "HarmBlockUnspecified",
	HarmBlockLowAndAbove:    "HarmBlockLowAndAbove",
	HarmBlockMediumAndAbove: "HarmBlockMediumAndAbove",
	HarmBlockOnlyHigh:       "HarmBlockOnlyHigh",
	HarmBlockNone:           "HarmBlockNone",
}

func (v HarmBlockThreshold) String() string {
	if n, ok := namesForHarmBlockThreshold[v]; ok {
		return n
	}
	return fmt.Sprintf("HarmBlockThreshold(%d)", v)
}

// HarmCategory specifies the category of a rating.
//
// These categories cover various kinds of harms that developers
// may wish to adjust.
type HarmCategory int32

const (
	// HarmCategoryUnspecified means category is unspecified.
	HarmCategoryUnspecified HarmCategory = 0
	// HarmCategoryDerogatory means negative or harmful comments targeting identity and/or protected attribute.
	HarmCategoryDerogatory HarmCategory = 1
	// HarmCategoryToxicity means content that is rude, disrespectful, or profane.
	HarmCategoryToxicity HarmCategory = 2
	// HarmCategoryViolence means describes scenarios depicting violence against an individual or group, or
	// general descriptions of gore.
	HarmCategoryViolence HarmCategory = 3
	// HarmCategorySexual means contains references to sexual acts or other lewd content.
	HarmCategorySexual HarmCategory = 4
	// HarmCategoryMedical means promotes unchecked medical advice.
	HarmCategoryMedical HarmCategory = 5
	// HarmCategoryDangerous means dangerous content that promotes, facilitates, or encourages harmful acts.
	HarmCategoryDangerous HarmCategory = 6
	// HarmCategoryHarassment means harasment content.
	HarmCategoryHarassment HarmCategory = 7
	// HarmCategoryHateSpeech means hate speech and content.
	HarmCategoryHateSpeech HarmCategory = 8
	// HarmCategorySexuallyExplicit means sexually explicit content.
	HarmCategorySexuallyExplicit HarmCategory = 9
	// HarmCategoryDangerousContent means dangerous content.
	HarmCategoryDangerousContent HarmCategory = 10
)

var namesForHarmCategory = map[HarmCategory]string{
	HarmCategoryUnspecified:      "HarmCategoryUnspecified",
	HarmCategoryDerogatory:       "HarmCategoryDerogatory",
	HarmCategoryToxicity:         "HarmCategoryToxicity",
	HarmCategoryViolence:         "HarmCategoryViolence",
	HarmCategorySexual:           "HarmCategorySexual",
	HarmCategoryMedical:          "HarmCategoryMedical",
	HarmCategoryDangerous:        "HarmCategoryDangerous",
	HarmCategoryHarassment:       "HarmCategoryHarassment",
	HarmCategoryHateSpeech:       "HarmCategoryHateSpeech",
	HarmCategorySexuallyExplicit: "HarmCategorySexuallyExplicit",
	HarmCategoryDangerousContent: "HarmCategoryDangerousContent",
}

func (v HarmCategory) String() string {
	if n, ok := namesForHarmCategory[v]; ok {
		return n
	}
	return fmt.Sprintf("HarmCategory(%d)", v)
}

// HarmProbability specifies the probability that a piece of content is harmful.
//
// The classification system gives the probability of the content being
// unsafe. This does not indicate the severity of harm for a piece of content.
type HarmProbability int32

const (
	// HarmProbabilityUnspecified means probability is unspecified.
	HarmProbabilityUnspecified HarmProbability = 0
	// HarmProbabilityNegligible means content has a negligible chance of being unsafe.
	HarmProbabilityNegligible HarmProbability = 1
	// HarmProbabilityLow means content has a low chance of being unsafe.
	HarmProbabilityLow HarmProbability = 2
	// HarmProbabilityMedium means content has a medium chance of being unsafe.
	HarmProbabilityMedium HarmProbability = 3
	// HarmProbabilityHigh means content has a high chance of being unsafe.
	HarmProbabilityHigh HarmProbability = 4
)

var namesForHarmProbability = map[HarmProbability]string{
	HarmProbabilityUnspecified: "HarmProbabilityUnspecified",
	HarmProbabilityNegligible:  "HarmProbabilityNegligible",
	HarmProbabilityLow:         "HarmProbabilityLow",
	HarmProbabilityMedium:      "HarmProbabilityMedium",
	HarmProbabilityHigh:        "HarmProbabilityHigh",
}

func (v HarmProbability) String() string {
	if n, ok := namesForHarmProbability[v]; ok {
		return n
	}
	return fmt.Sprintf("HarmProbability(%d)", v)
}

// ModelInfo is information about a language model.
type ModelInfo struct {
	// Required. The resource name of the `Model`.
	//
	// Format: `models/{model}` with a `{model}` naming convention of:
	//
	// * "{base_model_id}-{version}"
	//
	// Examples:
	//
	// * `models/chat-bison-001`
	Name string
	// Required. The name of the base model, pass this to the generation request.
	//
	// Examples:
	//
	// * `chat-bison`
	BaseModelID string
	// Required. The version number of the model.
	//
	// This represents the major version
	Version string
	// The human-readable name of the model. E.g. "Chat Bison".
	//
	// The name can be up to 128 characters long and can consist of any UTF-8
	// characters.
	DisplayName string
	// A short description of the model.
	Description string
	// Maximum number of input tokens allowed for this model.
	InputTokenLimit int32
	// Maximum number of output tokens available for this model.
	OutputTokenLimit int32
	// The model's supported generation methods.
	//
	// The method names are defined as Pascal case
	// strings, such as `generateMessage` which correspond to API methods.
	SupportedGenerationMethods []string
	// Controls the randomness of the output.
	//
	// Values can range over `[0.0,max_temperature]`, inclusive. A higher value
	// will produce responses that are more varied, while a value closer to `0.0`
	// will typically result in less surprising responses from the model.
	// This value specifies default to be used by the backend while making the
	// call to the model.
	Temperature float32
	// The maximum temperature this model can use.
	MaxTemperature *float32
	// For Nucleus sampling.
	//
	// Nucleus sampling considers the smallest set of tokens whose probability
	// sum is at least `top_p`.
	// This value specifies default to be used by the backend while making the
	// call to the model.
	TopP float32
	// For Top-k sampling.
	//
	// Top-k sampling considers the set of `top_k` most probable tokens.
	// This value specifies default to be used by the backend while making the
	// call to the model.
	// If empty, indicates the model doesn't use top-k sampling, and `top_k` isn't
	// allowed as a generation parameter.
	TopK int32
}

func (v *ModelInfo) toProto() *pb.Model {
	if v == nil {
		return nil
	}
	return &pb.Model{
		Name:                       v.Name,
		BaseModelId:                v.BaseModelID,
		Version:                    v.Version,
		DisplayName:                v.DisplayName,
		Description:                v.Description,
		InputTokenLimit:            v.InputTokenLimit,
		OutputTokenLimit:           v.OutputTokenLimit,
		SupportedGenerationMethods: v.SupportedGenerationMethods,
		Temperature:                pvAddrOrNil(v.Temperature),
		MaxTemperature:             v.MaxTemperature,
		TopP:                       pvAddrOrNil(v.TopP),
		TopK:                       pvAddrOrNil(v.TopK),
	}
}

func (ModelInfo) fromProto(p *pb.Model) *ModelInfo {
	if p == nil {
		return nil
	}
	return &ModelInfo{
		Name:                       p.Name,
		BaseModelID:                p.BaseModelId,
		Version:                    p.Version,
		DisplayName:                p.DisplayName,
		Description:                p.Description,
		InputTokenLimit:            p.InputTokenLimit,
		OutputTokenLimit:           p.OutputTokenLimit,
		SupportedGenerationMethods: p.SupportedGenerationMethods,
		Temperature:                pvDerefOrZero(p.Temperature),
		MaxTemperature:             p.MaxTemperature,
		TopP:                       pvDerefOrZero(p.TopP),
		TopK:                       pvDerefOrZero(p.TopK),
	}
}

// PromptFeedback contains a set of the feedback metadata the prompt specified in
// `GenerateContentRequest.content`.
type PromptFeedback struct {
	// Optional. If set, the prompt was blocked and no candidates are returned.
	// Rephrase your prompt.
	BlockReason BlockReason
	// Ratings for safety of the prompt.
	// There is at most one rating per category.
	SafetyRatings []*SafetyRating
}

func (v *PromptFeedback) toProto() *pb.GenerateContentResponse_PromptFeedback {
	if v == nil {
		return nil
	}
	return &pb.GenerateContentResponse_PromptFeedback{
		BlockReason:   pb.GenerateContentResponse_PromptFeedback_BlockReason(v.BlockReason),
		SafetyRatings: pvTransformSlice(v.SafetyRatings, (*SafetyRating).toProto),
	}
}

func (PromptFeedback) fromProto(p *pb.GenerateContentResponse_PromptFeedback) *PromptFeedback {
	if p == nil {
		return nil
	}
	return &PromptFeedback{
		BlockReason:   BlockReason(p.BlockReason),
		SafetyRatings: pvTransformSlice(p.SafetyRatings, (SafetyRating{}).fromProto),
	}
}

// SafetyRating is the safety rating for a piece of content.
//
// The safety rating contains the category of harm and the
// harm probability level in that category for a piece of content.
// Content is classified for safety across a number of
// harm categories and the probability of the harm classification is included
// here.
type SafetyRating struct {
	// Required. The category for this rating.
	Category HarmCategory
	// Required. The probability of harm for this content.
	Probability HarmProbability
	// Was this content blocked because of this rating?
	Blocked bool
}

func (v *SafetyRating) toProto() *pb.SafetyRating {
	if v == nil {
		return nil
	}
	return &pb.SafetyRating{
		Category:    pb.HarmCategory(v.Category),
		Probability: pb.SafetyRating_HarmProbability(v.Probability),
		Blocked:     v.Blocked,
	}
}

func (SafetyRating) fromProto(p *pb.SafetyRating) *SafetyRating {
	if p == nil {
		return nil
	}
	return &SafetyRating{
		Category:    HarmCategory(p.Category),
		Probability: HarmProbability(p.Probability),
		Blocked:     p.Blocked,
	}
}

// SafetySetting is safety setting, affecting the safety-blocking behavior.
//
// Passing a safety setting for a category changes the allowed probability that
// content is blocked.
type SafetySetting struct {
	// Required. The category for this setting.
	Category HarmCategory
	// Required. Controls the probability threshold at which harm is blocked.
	Threshold HarmBlockThreshold
}

func (v *SafetySetting) toProto() *pb.SafetySetting {
	if v == nil {
		return nil
	}
	return &pb.SafetySetting{
		Category:  pb.HarmCategory(v.Category),
		Threshold: pb.SafetySetting_HarmBlockThreshold(v.Threshold),
	}
}

func (SafetySetting) fromProto(p *pb.SafetySetting) *SafetySetting {
	if p == nil {
		return nil
	}
	return &SafetySetting{
		Category:  HarmCategory(p.Category),
		Threshold: HarmBlockThreshold(p.Threshold),
	}
}

// Schema is the `Schema` object allows the definition of input and output data types.
// These types can be objects, but also primitives and arrays.
// Represents a select subset of an [OpenAPI 3.0 schema
// object](https://spec.openapis.org/oas/v3.0.3#schema).
type Schema struct {
	// Required. Data type.
	Type Type
	// Optional. The format of the data. This is used only for primitive
	// datatypes. Supported formats:
	//
	//	for NUMBER type: float, double
	//	for INTEGER type: int32, int64
	Format string
	// Optional. A brief description of the parameter. This could contain examples
	// of use. Parameter description may be formatted as Markdown.
	Description string
	// Optional. Indicates if the value may be null.
	Nullable bool
	// Optional. Possible values of the element of Type.STRING with enum format.
	// For example we can define an Enum Direction as :
	// {type:STRING, format:enum, enum:["EAST", NORTH", "SOUTH", "WEST"]}
	Enum []string
	// Optional. Schema of the elements of Type.ARRAY.
	Items *Schema
	// Optional. Properties of Type.OBJECT.
	Properties map[string]*Schema
	// Optional. Required properties of Type.OBJECT.
	Required []string
}

func (v *Schema) toProto() *pb.Schema {
	if v == nil {
		return nil
	}
	return &pb.Schema{
		Type:        pb.Type(v.Type),
		Format:      v.Format,
		Description: v.Description,
		Nullable:    v.Nullable,
		Enum:        v.Enum,
		Items:       v.Items.toProto(),
		Properties:  pvTransformMapValues(v.Properties, (*Schema).toProto),
		Required:    v.Required,
	}
}

func (Schema) fromProto(p *pb.Schema) *Schema {
	if p == nil {
		return nil
	}
	return &Schema{
		Type:        Type(p.Type),
		Format:      p.Format,
		Description: p.Description,
		Nullable:    p.Nullable,
		Enum:        p.Enum,
		Items:       (Schema{}).fromProto(p.Items),
		Properties:  pvTransformMapValues(p.Properties, (Schema{}).fromProto),
		Required:    p.Required,
	}
}

// TaskType is type of task for which the embedding will be used.
type TaskType int32

const (
	// TaskTypeUnspecified means unset value, which will default to one of the other enum values.
	TaskTypeUnspecified TaskType = 0
	// TaskTypeRetrievalQuery means specifies the given text is a query in a search/retrieval setting.
	TaskTypeRetrievalQuery TaskType = 1
	// TaskTypeRetrievalDocument means specifies the given text is a document from the corpus being searched.
	TaskTypeRetrievalDocument TaskType = 2
	// TaskTypeSemanticSimilarity means specifies the given text will be used for STS.
	TaskTypeSemanticSimilarity TaskType = 3
	// TaskTypeClassification means specifies that the given text will be classified.
	TaskTypeClassification TaskType = 4
	// TaskTypeClustering means specifies that the embeddings will be used for clustering.
	TaskTypeClustering TaskType = 5
	// TaskTypeQuestionAnswering means specifies that the given text will be used for question answering.
	TaskTypeQuestionAnswering TaskType = 6
	// TaskTypeFactVerification means specifies that the given text will be used for fact verification.
	TaskTypeFactVerification TaskType = 7
)

var namesForTaskType = map[TaskType]string{
	TaskTypeUnspecified:        "TaskTypeUnspecified",
	TaskTypeRetrievalQuery:     "TaskTypeRetrievalQuery",
	TaskTypeRetrievalDocument:  "TaskTypeRetrievalDocument",
	TaskTypeSemanticSimilarity: "TaskTypeSemanticSimilarity",
	TaskTypeClassification:     "TaskTypeClassification",
	TaskTypeClustering:         "TaskTypeClustering",
	TaskTypeQuestionAnswering:  "TaskTypeQuestionAnswering",
	TaskTypeFactVerification:   "TaskTypeFactVerification",
}

func (v TaskType) String() string {
	if n, ok := namesForTaskType[v]; ok {
		return n
	}
	return fmt.Sprintf("TaskType(%d)", v)
}

// Tool details that the model may use to generate response.
//
// A `Tool` is a piece of code that enables the system to interact with
// external systems to perform an action, or set of actions, outside of
// knowledge and scope of the model.
type Tool struct {
	// Optional. A list of FunctionDeclarations available to the model that
	// can be used for function calling. The model or system does not execute
	// the function. Instead the defined function may be returned as a [FunctionCall]
	// part with arguments to the client side for execution. The next conversation
	// turn may contain a [FunctionResponse] with the role "function" generation
	// context for the next model turn.
	FunctionDeclarations []*FunctionDeclaration
	// Optional. Enables the model to execute code as part of generation.
	CodeExecution *CodeExecution
}

func (v *Tool) toProto() *pb.Tool {
	if v == nil {
		return nil
	}
	return &pb.Tool{
		FunctionDeclarations: pvTransformSlice(v.FunctionDeclarations, (*FunctionDeclaration).toProto),
		CodeExecution:        v.CodeExecution.toProto(),
	}
}

func (Tool) fromProto(p *pb.Tool) *Tool {
	if p == nil {
		return nil
	}
	return &Tool{
		FunctionDeclarations: pvTransformSlice(p.FunctionDeclarations, (FunctionDeclaration{}).fromProto),
		CodeExecution:        (CodeExecution{}).fromProto(p.CodeExecution),
	}
}

// ToolConfig is the Tool configuration containing parameters for specifying `Tool` use
// in the request.
type ToolConfig struct {
	// Optional. Function calling config.
	FunctionCallingConfig *FunctionCallingConfig
}

func (v *ToolConfig) toProto() *pb.ToolConfig {
	if v == nil {
		return nil
	}
	return &pb.ToolConfig{
		FunctionCallingConfig: v.FunctionCallingConfig.toProto(),
	}
}

func (ToolConfig) fromProto(p *pb.ToolConfig) *ToolConfig {
	if p == nil {
		return nil
	}
	return &ToolConfig{
		FunctionCallingConfig: (FunctionCallingConfig{}).fromProto(p.FunctionCallingConfig),
	}
}

// Type contains the list of OpenAPI data types as defined by
// https://spec.openapis.org/oas/v3.0.3#data-types
type Type int32

const (
	// TypeUnspecified means not specified, should not be used.
	TypeUnspecified Type = 0
	// TypeString means string type.
	TypeString Type = 1
	// TypeNumber means number type.
	TypeNumber Type = 2
	// TypeInteger means integer type.
	TypeInteger Type = 3
	// TypeBoolean means boolean type.
	TypeBoolean Type = 4
	// TypeArray means array type.
	TypeArray Type = 5
	// TypeObject means object type.
	TypeObject Type = 6
)

var namesForType = map[Type]string{
	TypeUnspecified: "TypeUnspecified",
	TypeString:      "TypeString",
	TypeNumber:      "TypeNumber",
	TypeInteger:     "TypeInteger",
	TypeBoolean:     "TypeBoolean",
	TypeArray:       "TypeArray",
	TypeObject:      "TypeObject",
}

func (v Type) String() string {
	if n, ok := namesForType[v]; ok {
		return n
	}
	return fmt.Sprintf("Type(%d)", v)
}

// UsageMetadata is metadata on the generation request's token usage.
type UsageMetadata struct {
	// Number of tokens in the prompt. When cached_content is set, this is still
	// the total effective prompt size. I.e. this includes the number of tokens
	// in the cached content.
	PromptTokenCount int32
	// Number of tokens in the cached part of the prompt, i.e. in the cached
	// content.
	CachedContentTokenCount int32
	// Total number of tokens across the generated candidates.
	CandidatesTokenCount int32
	// Total token count for the generation request (prompt + candidates).
	TotalTokenCount int32
}

func (v *UsageMetadata) toProto() *pb.GenerateContentResponse_UsageMetadata {
	if v == nil {
		return nil
	}
	return &pb.GenerateContentResponse_UsageMetadata{
		PromptTokenCount:        v.PromptTokenCount,
		CachedContentTokenCount: v.CachedContentTokenCount,
		CandidatesTokenCount:    v.CandidatesTokenCount,
		TotalTokenCount:         v.TotalTokenCount,
	}
}

func (UsageMetadata) fromProto(p *pb.GenerateContentResponse_UsageMetadata) *UsageMetadata {
	if p == nil {
		return nil
	}
	return &UsageMetadata{
		PromptTokenCount:        p.PromptTokenCount,
		CachedContentTokenCount: p.CachedContentTokenCount,
		CandidatesTokenCount:    p.CandidatesTokenCount,
		TotalTokenCount:         p.TotalTokenCount,
	}
}

// VideoMetadata is metadata for a video `File`.
type VideoMetadata struct {
	// Duration of the video.
	Duration time.Duration
}

func (v *VideoMetadata) toProto() *pb.VideoMetadata {
	if v == nil {
		return nil
	}
	return &pb.VideoMetadata{
		VideoDuration: durationpb.New(v.Duration),
	}
}

func (VideoMetadata) fromProto(p *pb.VideoMetadata) *VideoMetadata {
	if p == nil {
		return nil
	}
	return &VideoMetadata{
		Duration: pvDurationFromProto(p.VideoDuration),
	}
}

func pvTransformSlice[From, To any](from []From, f func(From) To) []To {
	if from == nil {
		return nil
	}
	to := make([]To, len(from))
	for i, e := range from {
		to[i] = f(e)
	}
	return to
}

func pvTransformMapValues[K comparable, VFrom, VTo any](from map[K]VFrom, f func(VFrom) VTo) map[K]VTo {
	if from == nil {
		return nil
	}
	to := map[K]VTo{}
	for k, v := range from {
		to[k] = f(v)
	}
	return to
}

func pvAddrOrNil[T comparable](x T) *T {
	var z T
	if x == z {
		return nil
	}
	return &x
}

func pvDerefOrZero[T any](x *T) T {
	if x == nil {
		var z T
		return z
	}
	return *x
}

func pvMapToStructPB(m map[string]any) *structpb.Struct {
	if m == nil {
		return nil
	}
	s, err := structpb.NewStruct(m)
	if err != nil {
		panic(pvPanic(fmt.Errorf("pvMapToStructPB: %w", err)))
	}
	return s
}

func pvMapFromStructPB(p *structpb.Struct) map[string]any {
	if p == nil {
		return nil
	}
	return p.AsMap()
}

func pvTimeToProto(t time.Time) *timestamppb.Timestamp {
	if t.IsZero() {
		return nil
	}
	return timestamppb.New(t)
}

func pvTimeFromProto(ts *timestamppb.Timestamp) time.Time {
	if ts == nil {
		return time.Time{}
	}
	return ts.AsTime()
}

func pvAPIErrorToProto(ae *apierror.APIError) *spb.Status {
	if ae == nil {
		return nil
	}
	return ae.GRPCStatus().Proto()
}

func pvAPIErrorFromProto(s *spb.Status) *apierror.APIError {
	err := gstatus.ErrorProto(s)
	aerr, ok := apierror.ParseError(err, true)
	if !ok {
		// Should be impossible.
		return nil
	}
	return aerr
}

func pvDurationFromProto(d *durationpb.Duration) time.Duration {
	if d == nil {
		return 0
	}
	return d.AsDuration()
}

// pvPanic wraps panics from support functions.
// User-provided functions in the same package can also use it.
// It allows callers to distinguish conversion function panics from other panics.
type pvPanic error

// pvCatchPanic recovers from panics of type pvPanic and
// returns an error instead.
func pvCatchPanic[T any](f func() T) (_ T, err error) {
	defer func() {
		if r := recover(); r != nil {
			if _, ok := r.(pvPanic); ok {
				err = r.(error)
			} else {
				panic(r)
			}
		}
	}()
	return f(), nil
}
