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

package basic

import (
	"fmt"
	"time"

	"cloud.google.com/go/civil"
	pb "example.com/basic"
	"github.com/googleapis/gax-go/v2/apierror"
	spb "google.golang.org/genproto/googleapis/rpc/status"
	"google.golang.org/genproto/googleapis/type/date"
	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"
)

// Blob contains raw media bytes.
//
// Text should not be sent as raw bytes, use the 'text' field.
type Blob struct {
	// Required. The IANA standard MIME type of the source data.
	MIMEType string
	// Required. 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,
	}
}

// Citation contains source attributions for content.
type Citation struct {
	// Output only. Url reference of the attribution.
	URI string
	// Output only. Publication date of the attribution.
	PublicationDate civil.Date
	Struct          map[string]any
	CreateTime      time.Time
}

func (v *Citation) toProto() *pb.Citation {
	if v == nil {
		return nil
	}
	return &pb.Citation{
		Uri:             v.URI,
		PublicationDate: pvCivilDateToProto(v.PublicationDate),
		Struct:          pvMapToStructPB(v.Struct),
		CreateTime:      pvTimeToProto(v.CreateTime),
	}
}

func (Citation) fromProto(p *pb.Citation) *Citation {
	if p == nil {
		return nil
	}
	return &Citation{
		URI:             p.Uri,
		PublicationDate: pvCivilDateFromProto(p.PublicationDate),
		Struct:          pvMapFromStructPB(p.Struct),
		CreateTime:      pvTimeFromProto(p.CreateTime),
	}
}

// CitationMetadata is a collection of source attributions for a piece of content.
type CitationMetadata struct {
	// Output only. List of citations.
	Citations []*Citation
	CitMap    map[string]*Citation
}

func (v *CitationMetadata) toProto() *pb.CitationMetadata {
	if v == nil {
		return nil
	}
	return &pb.CitationMetadata{
		Citations: pvTransformSlice(v.Citations, (*Citation).toProto),
		CitMap:    pvTransformMapValues(v.CitMap, (*Citation).toProto),
	}
}

func (CitationMetadata) fromProto(p *pb.CitationMetadata) *CitationMetadata {
	if p == nil {
		return nil
	}
	return &CitationMetadata{
		Citations: pvTransformSlice(p.Citations, (Citation{}).fromProto),
		CitMap:    pvTransformMapValues(p.CitMap, (Citation{}).fromProto),
	}
}

type File struct {
	Error  *apierror.APIError
	Dur    time.Duration
	hidden *Client
}

func (v *File) toProto() *pb.File {
	if v == nil {
		return nil
	}
	return &pb.File{
		Error: pvAPIErrorToProto(v.Error),
		Dur:   durationpb.New(v.Dur),
	}
}

func (File) fromProto(p *pb.File) *File {
	if p == nil {
		return nil
	}
	return &File{
		Error: pvAPIErrorFromProto(p.Error),
		Dur:   pvDurationFromProto(p.Dur),
	}
}

// FinishReason is the reason why the model stopped generating tokens.
// If empty, the model has not stopped generating the tokens.
type FinishReason int32

const (
	// FinishReasonUnspecified means the finish reason is unspecified.
	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 token generation was stopped as the response was flagged for safety
	// reasons. NOTE: When streaming the Candidate.content will be empty if
	// content filters blocked the output.
	FinishReasonSafety FinishReason = 3
	// FinishReasonRecitation means the token generation was stopped as the response was flagged for
	// unauthorized citations.
	FinishReasonRecitation FinishReason = 4
	// FinishReasonOther means all other reasons that stopped the token generation
	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)
}

// GenerationConfig is generation config.
type GenerationConfig struct {
	// Optional. Controls the randomness of predictions.
	Temperature float32
	// Optional. Number of candidates to generate.
	CandidateCount int32
	// Optional. Stop sequences.
	StopSequences []string
	HarmCat       HarmCategory
	// The reason for finishing.
	FinishReason FinishReason
	CitMet       *CitationMetadata
	// Multiple lines of
	// documentation for this
	// field.
	TopK *int32
}

func (v *GenerationConfig) toProto() *pb.GenerationConfig {
	if v == nil {
		return nil
	}
	return &pb.GenerationConfig{
		Temperature:    pvAddrOrNil(v.Temperature),
		CandidateCount: pvAddrOrNil(v.CandidateCount),
		StopSequences:  v.StopSequences,
		HarmCat:        pb.HarmCategory(v.HarmCat),
		FinishReason:   pb.Candidate_FinishReason(v.FinishReason),
		CitMet:         v.CitMet.toProto(),
		TopK:           int32pToFloat32p(v.TopK),
	}
}

func (GenerationConfig) fromProto(p *pb.GenerationConfig) *GenerationConfig {
	if p == nil {
		return nil
	}
	return &GenerationConfig{
		Temperature:    pvDerefOrZero(p.Temperature),
		CandidateCount: pvDerefOrZero(p.CandidateCount),
		StopSequences:  p.StopSequences,
		HarmCat:        HarmCategory(p.HarmCat),
		FinishReason:   FinishReason(p.FinishReason),
		CitMet:         (CitationMetadata{}).fromProto(p.CitMet),
		TopK:           float32pToInt32p(p.TopK),
	}
}

// HarmCategory specifies harm categories that will block the content.
type HarmCategory int32

const (
	// HarmCategoryUnspecified means the harm category is unspecified.
	HarmCategoryUnspecified HarmCategory = 0
	// HarmCategoryHateSpeech means the harm category is hate speech.
	HarmCategoryHateSpeech HarmCategory = 1
	// HarmCategoryDangerousContent means the harm category is dangerous content.
	HarmCategoryDangerousContent HarmCategory = 2
	// HarmCategoryHarassment means the harm category is harassment.
	HarmCategoryHarassment HarmCategory = 3
	// HarmCategorySexuallyExplicit means the harm category is sexually explicit content.
	HarmCategorySexuallyExplicit HarmCategory = 4
)

var namesForHarmCategory = map[HarmCategory]string{
	HarmCategoryUnspecified:      "HarmCategoryUnspecified",
	HarmCategoryHateSpeech:       "HarmCategoryHateSpeech",
	HarmCategoryDangerousContent: "HarmCategoryDangerousContent",
	HarmCategoryHarassment:       "HarmCategoryHarassment",
	HarmCategorySexuallyExplicit: "HarmCategorySexuallyExplicit",
}

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

// Pop is this demonstrates using population functions to deal with
// proto oneof field, which has an unexported type.
// That can be a way to deal with proto oneofs.
type Pop struct {
	X int
	Y unexported
}

func (v *Pop) toProto() *pb.Pop {
	if v == nil {
		return nil
	}
	p := &pb.Pop{
		X: v.X,
	}
	popYTo(p, v)
	return p
}

func (Pop) fromProto(p *pb.Pop) *Pop {
	if p == nil {
		return nil
	}
	v := &Pop{
		X: p.X,
	}
	popYFrom(v, p)
	return v
}

// pvTransformSlice applies f to each element of from and returns
// a new slice with the results.
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
}

// pvTransformMapValues applies f to each value of from, returning a new map.
// It does not change the keys.
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
}

// pvAddrOrNil returns nil if x is the zero value for T,
// or &x otherwise.
func pvAddrOrNil[T comparable](x T) *T {
	var z T
	if x == z {
		return nil
	}
	return &x
}

// pvDerefOrZero returns the zero value for T if x is nil,
// or *x otherwise.
func pvDerefOrZero[T any](x *T) T {
	if x == nil {
		var z T
		return z
	}
	return *x
}

// pvCivilDateToProto converts a civil.Date to a date.Date.
func pvCivilDateToProto(d civil.Date) *date.Date {
	return &date.Date{
		Year:  int32(d.Year),
		Month: int32(d.Month),
		Day:   int32(d.Day),
	}
}

// pvCivilDateFromProto converts a date.Date to a civil.Date.
func pvCivilDateFromProto(p *date.Date) civil.Date {
	if p == nil {
		return civil.Date{}
	}
	return civil.Date{
		Year:  int(p.Year),
		Month: time.Month(p.Month),
		Day:   int(p.Day),
	}
}

// pvMapToStructPB converts a map into a structpb.Struct.
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
}

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

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

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

// pvAPIErrorToProto converts an APIError to a proto Status.
func pvAPIErrorToProto(ae *apierror.APIError) *spb.Status {
	if ae == nil {
		return nil
	}
	return ae.GRPCStatus().Proto()
}

// pvAPIErrorFromProto converts a proto Status to an APIError.
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
}

// pvDurationFromProto converts a Duration proto to a time.Duration.
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
}
