package mapping

import (
	"context"

	semantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/queryv1"
	commonv1 "github.com/pingcap-inc/nexuscrm-contract/wire-go/gen/common/v1"
	runtimev1 "github.com/pingcap-inc/nexuscrm-contract/wire-go/gen/runtime/v1"
)

func ToWireQueryRecordsRequest(ctx context.Context, request semantic.Request) (*runtimev1.QueryRecordsRequest, error) {
	if err := semantic.ValidateRequest(ctx, request); err != nil {
		return nil, err
	}
	filter, err := toWireQueryPredicate(request.Filter)
	if err != nil {
		return nil, err
	}
	having, err := toWireQueryPredicate(request.Having)
	if err != nil {
		return nil, err
	}
	subqueries := make([]*runtimev1.QuerySubquery, 0, len(request.Subqueries))
	for _, sub := range request.Subqueries {
		predicate, err := toWireQueryPredicate(sub.Filter)
		if err != nil {
			return nil, err
		}
		subqueries = append(subqueries, &runtimev1.QuerySubquery{RelationshipName: sub.RelationshipName, SelectedFields: append([]string(nil), sub.SelectedFields...), Filter: predicate, OrderBy: toWireQuerySorts(sub.OrderBy), Limit: sub.Limit})
	}
	return &runtimev1.QueryRecordsRequest{
		ObjectId: request.ObjectID, Selections: toWireQuerySelections(request.Selections), Filter: filter,
		Limit: request.Limit, Offset: request.Offset,
		SkipTotalSize: request.SkipTotalSize, IncludeDeleted: request.IncludeDeleted, OrderBy: toWireQuerySorts(request.OrderBy),
		GroupBy: request.GroupBy, Having: having, Subqueries: subqueries, AggregateFetchLimit: request.AggregateFetchLimit,
		MinCatalogRevision: request.MinCatalogRevision,
	}, nil
}

func FromWireQueryRecordsRequest(ctx context.Context, request *runtimev1.QueryRecordsRequest) (semantic.Request, error) {
	if request == nil {
		return semantic.Request{}, &semantic.Failure{Category: semantic.FailureInvalidRequest, InvalidComponent: semantic.InvalidComponentQueryPlan}
	}
	budget := queryDecodeBudget{}
	filter, err := fromWireQueryPredicate(request.GetFilter(), 1, &budget)
	if err != nil {
		return semantic.Request{}, err
	}
	having, err := fromWireQueryPredicate(request.GetHaving(), 1, &budget)
	if err != nil {
		return semantic.Request{}, err
	}
	orderBy, err := fromWireQuerySorts(request.GetOrderBy())
	if err != nil {
		return semantic.Request{}, err
	}
	result := semantic.Request{
		ObjectID: request.GetObjectId(), Filter: filter,
		Limit: request.GetLimit(), Offset: request.GetOffset(),
		SkipTotalSize: request.GetSkipTotalSize(), IncludeDeleted: request.GetIncludeDeleted(), OrderBy: orderBy,
		GroupBy: request.GetGroupBy(), Having: having, AggregateFetchLimit: request.GetAggregateFetchLimit(), MinCatalogRevision: request.MinCatalogRevision,
	}
	result.Selections, err = fromWireQuerySelections(request.GetSelections())
	if err != nil {
		return semantic.Request{}, err
	}
	for _, sub := range request.GetSubqueries() {
		if sub == nil {
			return semantic.Request{}, queryInternal()
		}
		predicate, err := fromWireQueryPredicate(sub.GetFilter(), 2, &budget)
		if err != nil {
			return semantic.Request{}, err
		}
		orderBy, err := fromWireQuerySorts(sub.GetOrderBy())
		if err != nil {
			return semantic.Request{}, err
		}
		result.Subqueries = append(result.Subqueries, semantic.Subquery{RelationshipName: sub.GetRelationshipName(), SelectedFields: append([]string(nil), sub.GetSelectedFields()...), Filter: predicate, OrderBy: orderBy, Limit: sub.GetLimit()})
	}
	if err := semantic.ValidateRequest(ctx, result); err != nil {
		return semantic.Request{}, err
	}
	return result, nil
}

func ToWireQueryRecordsResponse(response semantic.Response) (*runtimev1.QueryRecordsResponse, error) {
	if err := semantic.ValidateResponse(response); err != nil {
		return nil, err
	}
	records := make([]*runtimev1.QueryRecord, 0, len(response.Records))
	for _, record := range response.Records {
		wireRecord, err := toWireQueryRecord(record)
		if err != nil {
			return nil, err
		}
		records = append(records, wireRecord)
	}
	return &runtimev1.QueryRecordsResponse{
		TotalSize: response.TotalSize, TotalSizeUnknown: response.TotalSizeUnknown, Done: response.Done, Records: records, Aggregate: response.Aggregate,
		Receipts: &commonv1.ConsistencyReceipts{ProtocolVersion: &commonv1.ProtocolVersion{Major: semantic.ProtocolMajor, Minor: semantic.ProtocolMinor}, CatalogRevision: response.Receipts.CatalogRevision, SchemaGeneration: response.Receipts.SchemaGeneration, EngineGeneration: response.Receipts.EngineGeneration, SecurityEpoch: response.Receipts.SecurityEpoch, CapabilityVersion: &commonv1.CapabilityVersion{Name: semantic.CapabilityName, Major: 1, Minor: 0}},
	}, nil
}

func FromWireQueryRecordsResponse(response *runtimev1.QueryRecordsResponse) (semantic.Response, error) {
	if response == nil || response.GetReceipts() == nil || response.GetReceipts().GetProtocolVersion() == nil || response.GetReceipts().GetCapabilityVersion() == nil {
		return semantic.Response{}, queryIncompatible()
	}
	protocol, capability := response.GetReceipts().GetProtocolVersion(), response.GetReceipts().GetCapabilityVersion()
	if protocol.GetMajor() != semantic.ProtocolMajor || protocol.GetMinor() != semantic.ProtocolMinor || capability.GetName() != semantic.CapabilityName || capability.GetMajor() != 1 || capability.GetMinor() != 0 {
		return semantic.Response{}, queryIncompatible()
	}
	result := semantic.Response{TotalSize: response.GetTotalSize(), TotalSizeUnknown: response.GetTotalSizeUnknown(), Done: response.GetDone(), Aggregate: response.GetAggregate(), Receipts: semantic.Receipts{ProtocolVersion: "1.0", CatalogRevision: response.GetReceipts().GetCatalogRevision(), SchemaGeneration: response.GetReceipts().GetSchemaGeneration(), EngineGeneration: response.GetReceipts().GetEngineGeneration(), SecurityEpoch: response.GetReceipts().GetSecurityEpoch(), CapabilityVersion: semantic.CapabilityName}}
	for _, record := range response.GetRecords() {
		semanticRecord, err := fromWireQueryRecord(record, 1)
		if err != nil {
			return semantic.Response{}, err
		}
		result.Records = append(result.Records, semanticRecord)
	}
	if err := semantic.ValidateResponse(result); err != nil {
		return semantic.Response{}, err
	}
	return result, nil
}

func ToWireQueryHistoryRequest(ctx context.Context, request semantic.HistoryRequest) (*runtimev1.QueryHistoryRequest, error) {
	if err := semantic.ValidateHistoryRequest(ctx, request); err != nil {
		return nil, err
	}
	filter, err := toWireQueryPredicate(request.Filter)
	if err != nil {
		return nil, err
	}
	return &runtimev1.QueryHistoryRequest{
		ParentObjectId: request.ParentObjectID, SelectedFields: append([]string(nil), request.SelectedFields...),
		ParentRecordId: request.ParentRecordID, Filter: filter, Limit: request.Limit, Offset: request.Offset,
		SortDescending: request.SortDescending, IncludeDeleted: request.IncludeDeleted, PageSize: request.PageSize,
		CursorOffset: request.CursorOffset, MinCatalogRevision: request.MinCatalogRevision,
	}, nil
}

func FromWireQueryHistoryRequest(ctx context.Context, request *runtimev1.QueryHistoryRequest) (semantic.HistoryRequest, error) {
	if request == nil {
		return semantic.HistoryRequest{}, &semantic.Failure{Category: semantic.FailureInvalidRequest, InvalidComponent: semantic.InvalidComponentQueryPlan}
	}
	budget := queryDecodeBudget{}
	filter, err := fromWireQueryPredicate(request.GetFilter(), 1, &budget)
	if err != nil {
		return semantic.HistoryRequest{}, err
	}
	result := semantic.HistoryRequest{
		ParentObjectID: request.GetParentObjectId(), SelectedFields: append([]string(nil), request.GetSelectedFields()...),
		ParentRecordID: request.GetParentRecordId(), Filter: filter, Limit: request.GetLimit(), Offset: request.GetOffset(),
		SortDescending: request.GetSortDescending(), IncludeDeleted: request.GetIncludeDeleted(), PageSize: request.GetPageSize(),
		CursorOffset: request.GetCursorOffset(), MinCatalogRevision: request.MinCatalogRevision,
	}
	if err := semantic.ValidateHistoryRequest(ctx, result); err != nil {
		return semantic.HistoryRequest{}, err
	}
	return result, nil
}

func ToWireQueryHistoryResponse(response semantic.HistoryResponse) (*runtimev1.QueryHistoryResponse, error) {
	if err := semantic.ValidateHistoryResponse(response); err != nil {
		return nil, err
	}
	rows := make([]*runtimev1.QueryHistoryRow, 0, len(response.Rows))
	for _, row := range response.Rows {
		rows = append(rows, &runtimev1.QueryHistoryRow{Id: row.ID, ParentId: row.ParentID, Field: row.Field, OldValue: row.OldValue, NewValue: row.NewValue, DataType: row.DataType, CreatedDate: row.CreatedDate, CreatedById: row.CreatedByID})
	}
	return &runtimev1.QueryHistoryResponse{TotalSize: response.TotalSize, Done: response.Done, Rows: rows, Receipts: queryReceiptsToWire(response.Receipts)}, nil
}

func FromWireQueryHistoryResponse(response *runtimev1.QueryHistoryResponse) (semantic.HistoryResponse, error) {
	if response == nil {
		return semantic.HistoryResponse{}, queryIncompatible()
	}
	receipts, err := queryReceiptsFromWire(response.GetReceipts())
	if err != nil {
		return semantic.HistoryResponse{}, err
	}
	result := semantic.HistoryResponse{TotalSize: response.GetTotalSize(), Done: response.GetDone(), Receipts: receipts}
	for _, row := range response.GetRows() {
		if row == nil {
			return semantic.HistoryResponse{}, queryInternal()
		}
		result.Rows = append(result.Rows, semantic.HistoryRow{ID: row.GetId(), ParentID: row.GetParentId(), Field: row.GetField(), OldValue: row.OldValue, NewValue: row.NewValue, DataType: row.GetDataType(), CreatedDate: row.GetCreatedDate(), CreatedByID: row.GetCreatedById()})
	}
	if err := semantic.ValidateHistoryResponse(result); err != nil {
		return semantic.HistoryResponse{}, err
	}
	return result, nil
}

func queryReceiptsToWire(receipts semantic.Receipts) *commonv1.ConsistencyReceipts {
	return &commonv1.ConsistencyReceipts{ProtocolVersion: &commonv1.ProtocolVersion{Major: semantic.ProtocolMajor, Minor: semantic.ProtocolMinor}, CatalogRevision: receipts.CatalogRevision, SchemaGeneration: receipts.SchemaGeneration, EngineGeneration: receipts.EngineGeneration, SecurityEpoch: receipts.SecurityEpoch, CapabilityVersion: &commonv1.CapabilityVersion{Name: semantic.CapabilityName, Major: 1, Minor: 0}}
}

func queryReceiptsFromWire(receipts *commonv1.ConsistencyReceipts) (semantic.Receipts, error) {
	if receipts == nil || receipts.GetProtocolVersion() == nil || receipts.GetCapabilityVersion() == nil {
		return semantic.Receipts{}, queryIncompatible()
	}
	protocol, capability := receipts.GetProtocolVersion(), receipts.GetCapabilityVersion()
	if protocol.GetMajor() != semantic.ProtocolMajor || protocol.GetMinor() != semantic.ProtocolMinor || capability.GetName() != semantic.CapabilityName || capability.GetMajor() != 1 || capability.GetMinor() != 0 {
		return semantic.Receipts{}, queryIncompatible()
	}
	return semantic.Receipts{ProtocolVersion: "1.0", CatalogRevision: receipts.GetCatalogRevision(), SchemaGeneration: receipts.GetSchemaGeneration(), EngineGeneration: receipts.GetEngineGeneration(), SecurityEpoch: receipts.GetSecurityEpoch(), CapabilityVersion: semantic.CapabilityName}, nil
}

func toWireQuerySorts(values []semantic.Sort) []*runtimev1.QuerySort {
	result := make([]*runtimev1.QuerySort, 0, len(values))
	for _, value := range values {
		result = append(result, &runtimev1.QuerySort{Field: value.Field, Direction: toWireQuerySortDirection(value.Direction)})
	}
	return result
}
func fromWireQuerySorts(values []*runtimev1.QuerySort) ([]semantic.Sort, error) {
	if len(values) == 0 {
		return nil, nil
	}
	result := make([]semantic.Sort, 0, len(values))
	for _, value := range values {
		if value == nil {
			return nil, queryInternal()
		}
		direction, ok := fromWireQuerySortDirection(value.GetDirection())
		if !ok {
			return nil, queryInternal()
		}
		result = append(result, semantic.Sort{Field: value.GetField(), Direction: direction})
	}
	return result, nil
}

func toWireQuerySelections(values []semantic.Selection) []*runtimev1.QuerySelection {
	result := make([]*runtimev1.QuerySelection, 0, len(values))
	for _, value := range values {
		result = append(result, &runtimev1.QuerySelection{
			Kind:      toWireQuerySelectionKind(value.Kind),
			Field:     value.Field,
			Aggregate: toWireQueryAggregateFunction(value.Aggregate),
			Alias:     value.Alias,
		})
	}
	return result
}

func fromWireQuerySelections(values []*runtimev1.QuerySelection) ([]semantic.Selection, error) {
	result := make([]semantic.Selection, 0, len(values))
	for _, value := range values {
		if value == nil {
			return nil, queryInternal()
		}
		kind, ok := fromWireQuerySelectionKind(value.GetKind())
		if !ok {
			return nil, queryInternal()
		}
		aggregate, ok := fromWireQueryAggregateFunction(value.GetAggregate())
		if !ok {
			return nil, queryInternal()
		}
		result = append(result, semantic.Selection{Kind: kind, Field: value.GetField(), Aggregate: aggregate, Alias: value.GetAlias()})
	}
	return result, nil
}

func toWireQueryPredicate(value semantic.Predicate) (*runtimev1.QueryPredicate, error) {
	if value.Kind == semantic.PredicateNone {
		return nil, nil
	}
	result := &runtimev1.QueryPredicate{Kind: toWireQueryPredicateKind(value.Kind)}
	switch value.Kind {
	case semantic.PredicateAnd, semantic.PredicateOr, semantic.PredicateNot:
		children := make([]*runtimev1.QueryPredicate, 0, len(value.Children))
		for _, child := range value.Children {
			item, err := toWireQueryPredicate(child)
			if err != nil {
				return nil, err
			}
			children = append(children, item)
		}
		result.Value = &runtimev1.QueryPredicate_Children{Children: &runtimev1.QueryPredicates{Values: children}}
	case semantic.PredicateExpression:
		operand, err := toWireQueryOperand(value.Operand)
		if err != nil {
			return nil, err
		}
		result.Value = &runtimev1.QueryPredicate_Expression{Expression: operand}
	case semantic.PredicateComparison:
		left, err := toWireQueryOperand(value.Left)
		if err != nil {
			return nil, err
		}
		right, err := toWireQueryOperand(value.Right)
		if err != nil {
			return nil, err
		}
		result.Value = &runtimev1.QueryPredicate_Comparison{Comparison: &runtimev1.QueryComparison{Left: left, Operator: toWireQueryComparisonOperator(value.Operator), Right: right}}
	case semantic.PredicateFieldComparison:
		scalar, err := toWireQueryScalar(value.Value)
		if err != nil {
			return nil, err
		}
		result.Value = &runtimev1.QueryPredicate_FieldComparison{FieldComparison: &runtimev1.QueryFieldComparison{Field: value.Field, Operator: toWireQueryComparisonOperator(value.Operator), Value: scalar}}
	case semantic.PredicateCorrelatedMembership:
		if value.CorrelatedMembership == nil {
			return nil, queryInternal()
		}
		inner, err := toWireQueryPredicate(value.CorrelatedMembership.InnerFilter)
		if err != nil {
			return nil, err
		}
		m := value.CorrelatedMembership
		result.Value = &runtimev1.QueryPredicate_CorrelatedMembership{CorrelatedMembership: &runtimev1.QueryCorrelatedMembership{Id: m.ID, OuterField: m.OuterField, Negate: m.Negate, InnerObjectId: m.InnerObjectID, InnerSelectField: m.InnerSelectField, InnerFilter: inner, InnerLimit: m.InnerLimit, InnerIncludeDeleted: m.InnerIncludeDeleted}}
	default:
		return nil, queryInternal()
	}
	return result, nil
}

func fromWireQueryPredicate(value *runtimev1.QueryPredicate, depth int, budget *queryDecodeBudget) (semantic.Predicate, error) {
	if value == nil {
		return semantic.Predicate{}, nil
	}
	if err := budget.enter(depth); err != nil {
		return semantic.Predicate{}, err
	}
	result := semantic.Predicate{Kind: fromWireQueryPredicateKind(value.GetKind())}
	if result.Kind == semantic.PredicateNone {
		return semantic.Predicate{}, queryInternal()
	}
	switch arm := value.GetValue().(type) {
	case *runtimev1.QueryPredicate_Children:
		if result.Kind != semantic.PredicateAnd && result.Kind != semantic.PredicateOr && result.Kind != semantic.PredicateNot {
			return semantic.Predicate{}, queryInternal()
		}
		if arm.Children == nil {
			return semantic.Predicate{}, queryInternal()
		}
		for _, child := range arm.Children.GetValues() {
			item, err := fromWireQueryPredicate(child, depth+1, budget)
			if err != nil {
				return semantic.Predicate{}, err
			}
			result.Children = append(result.Children, item)
		}
	case *runtimev1.QueryPredicate_Expression:
		if result.Kind != semantic.PredicateExpression {
			return semantic.Predicate{}, queryInternal()
		}
		operand, err := fromWireQueryOperand(arm.Expression, depth+1, budget)
		if err != nil {
			return semantic.Predicate{}, err
		}
		result.Operand = operand
	case *runtimev1.QueryPredicate_Comparison:
		if result.Kind != semantic.PredicateComparison {
			return semantic.Predicate{}, queryInternal()
		}
		if arm.Comparison == nil {
			return semantic.Predicate{}, queryInternal()
		}
		left, err := fromWireQueryOperand(arm.Comparison.GetLeft(), depth+1, budget)
		if err != nil {
			return semantic.Predicate{}, err
		}
		right, err := fromWireQueryOperand(arm.Comparison.GetRight(), depth+1, budget)
		if err != nil {
			return semantic.Predicate{}, err
		}
		operator, ok := fromWireQueryComparisonOperator(arm.Comparison.GetOperator())
		if !ok {
			return semantic.Predicate{}, queryInternal()
		}
		result.Left, result.Right, result.Operator = left, right, operator
	case *runtimev1.QueryPredicate_FieldComparison:
		if result.Kind != semantic.PredicateFieldComparison {
			return semantic.Predicate{}, queryInternal()
		}
		if arm.FieldComparison == nil {
			return semantic.Predicate{}, queryInternal()
		}
		scalar, err := fromWireQueryScalar(arm.FieldComparison.GetValue())
		if err != nil {
			return semantic.Predicate{}, err
		}
		operator, ok := fromWireQueryComparisonOperator(arm.FieldComparison.GetOperator())
		if !ok {
			return semantic.Predicate{}, queryInternal()
		}
		result.Field, result.Operator, result.Value = arm.FieldComparison.GetField(), operator, &scalar
	case *runtimev1.QueryPredicate_CorrelatedMembership:
		if result.Kind != semantic.PredicateCorrelatedMembership {
			return semantic.Predicate{}, queryInternal()
		}
		if arm.CorrelatedMembership == nil {
			return semantic.Predicate{}, queryInternal()
		}
		inner, err := fromWireQueryPredicate(arm.CorrelatedMembership.GetInnerFilter(), depth+1, budget)
		if err != nil {
			return semantic.Predicate{}, err
		}
		m := arm.CorrelatedMembership
		result.CorrelatedMembership = &semantic.CorrelatedMembership{ID: m.GetId(), OuterField: m.GetOuterField(), Negate: m.GetNegate(), InnerObjectID: m.GetInnerObjectId(), InnerSelectField: m.GetInnerSelectField(), InnerFilter: inner, InnerLimit: m.GetInnerLimit(), InnerIncludeDeleted: m.GetInnerIncludeDeleted()}
	default:
		return semantic.Predicate{}, queryInternal()
	}
	return result, nil
}

func toWireQueryOperand(value semantic.Operand) (*runtimev1.QueryOperand, error) {
	result := &runtimev1.QueryOperand{Kind: toWireQueryOperandKind(value.Kind)}
	switch value.Kind {
	case semantic.OperandField:
		result.Value = &runtimev1.QueryOperand_Field{Field: value.Field}
	case semantic.OperandLiteral:
		scalar, err := toWireQueryScalar(value.Literal)
		if err != nil {
			return nil, err
		}
		result.Value = &runtimev1.QueryOperand_Literal{Literal: scalar}
	case semantic.OperandList:
		items := make([]*runtimev1.QueryOperand, 0, len(value.Elements))
		for _, item := range value.Elements {
			wireItem, err := toWireQueryOperand(item)
			if err != nil {
				return nil, err
			}
			items = append(items, wireItem)
		}
		result.Value = &runtimev1.QueryOperand_List{List: &runtimev1.QueryOperands{Values: items}}
	case semantic.OperandTrustedContext:
		result.Value = &runtimev1.QueryOperand_TrustedContext{TrustedContext: toWireQueryTrustedContext(value.TrustedContext)}
	case semantic.OperandFunction:
		args := make([]*runtimev1.QueryOperand, 0, len(value.Args))
		for _, arg := range value.Args {
			wireArg, err := toWireQueryOperand(arg)
			if err != nil {
				return nil, err
			}
			args = append(args, wireArg)
		}
		result.Value = &runtimev1.QueryOperand_Function{Function: &runtimev1.QueryFunction{
			Name: toWireQueryFunction(value.Function), Arguments: args,
			TemporalPart: toWireQueryTemporalPart(value.TemporalPart), TemporalBasis: toWireQueryTemporalBasis(value.TemporalBasis),
			DistanceUnit: toWireQueryDistanceUnit(value.DistanceUnit),
		}}
	default:
		return nil, queryInternal()
	}
	return result, nil
}

func fromWireQueryOperand(value *runtimev1.QueryOperand, depth int, budget *queryDecodeBudget) (semantic.Operand, error) {
	if err := budget.enter(depth); err != nil {
		return semantic.Operand{}, err
	}
	if value == nil {
		return semantic.Operand{}, queryInternal()
	}
	result := semantic.Operand{Kind: fromWireQueryOperandKind(value.GetKind())}
	switch arm := value.GetValue().(type) {
	case *runtimev1.QueryOperand_Field:
		result.Field = arm.Field
	case *runtimev1.QueryOperand_Literal:
		scalar, err := fromWireQueryScalar(arm.Literal)
		if err != nil {
			return semantic.Operand{}, err
		}
		result.Literal = &scalar
	case *runtimev1.QueryOperand_List:
		if arm.List == nil {
			return semantic.Operand{}, queryInternal()
		}
		for _, item := range arm.List.GetValues() {
			decoded, err := fromWireQueryOperand(item, depth+1, budget)
			if err != nil {
				return semantic.Operand{}, err
			}
			result.Elements = append(result.Elements, decoded)
		}
	case *runtimev1.QueryOperand_TrustedContext:
		trustedContext, ok := fromWireQueryTrustedContext(arm.TrustedContext)
		if !ok {
			return semantic.Operand{}, queryInternal()
		}
		result.TrustedContext = trustedContext
	case *runtimev1.QueryOperand_Function:
		if arm.Function == nil {
			return semantic.Operand{}, queryInternal()
		}
		function, ok := fromWireQueryFunction(arm.Function.GetName())
		if !ok {
			return semantic.Operand{}, queryInternal()
		}
		result.Function = function
		result.TemporalBasis, ok = fromWireQueryTemporalBasis(arm.Function.GetTemporalBasis())
		if !ok {
			return semantic.Operand{}, queryInternal()
		}
		result.TemporalPart, ok = fromWireQueryTemporalPart(arm.Function.GetTemporalPart())
		if !ok {
			return semantic.Operand{}, queryInternal()
		}
		result.DistanceUnit, ok = fromWireQueryDistanceUnit(arm.Function.GetDistanceUnit())
		if !ok {
			return semantic.Operand{}, queryInternal()
		}
		for _, arg := range arm.Function.GetArguments() {
			decoded, err := fromWireQueryOperand(arg, depth+1, budget)
			if err != nil {
				return semantic.Operand{}, err
			}
			result.Args = append(result.Args, decoded)
		}
	default:
		return semantic.Operand{}, queryInternal()
	}
	return result, nil
}

func toWireQueryScalar(value *semantic.Scalar) (*runtimev1.QueryScalar, error) {
	if value == nil {
		return nil, queryInternal()
	}
	result := &runtimev1.QueryScalar{}
	switch {
	case value.Null:
		result.Value = &runtimev1.QueryScalar_NullValue{NullValue: &runtimev1.NullValue{}}
	case value.String != nil:
		result.Value = &runtimev1.QueryScalar_StringValue{StringValue: *value.String}
	case value.Boolean != nil:
		result.Value = &runtimev1.QueryScalar_BooleanValue{BooleanValue: *value.Boolean}
	case value.Integer != nil:
		result.Value = &runtimev1.QueryScalar_IntegerValue{IntegerValue: *value.Integer}
	case value.Unsigned != nil:
		result.Value = &runtimev1.QueryScalar_UnsignedValue{UnsignedValue: *value.Unsigned}
	case value.Double != nil:
		result.Value = &runtimev1.QueryScalar_DoubleValue{DoubleValue: *value.Double}
	case value.Decimal != nil:
		result.Value = &runtimev1.QueryScalar_DecimalValue{DecimalValue: &runtimev1.DecimalValue{Coefficient: value.Decimal.Coefficient, Scale: value.Decimal.Scale}}
	case value.Date != nil:
		result.Value = &runtimev1.QueryScalar_DateValue{DateValue: &runtimev1.DateValue{CalendarDate: *value.Date}}
	case value.DateTime != nil:
		result.Value = &runtimev1.QueryScalar_DatetimeValue{DatetimeValue: &runtimev1.DateTimeValue{UtcRfc3339: *value.DateTime}}
	default:
		return nil, queryInternal()
	}
	return result, nil
}

func fromWireQueryScalar(value *runtimev1.QueryScalar) (semantic.Scalar, error) {
	if value == nil {
		return semantic.Scalar{}, queryInternal()
	}
	result := semantic.Scalar{}
	switch arm := value.GetValue().(type) {
	case *runtimev1.QueryScalar_NullValue:
		if arm.NullValue == nil {
			return result, queryInternal()
		}
		result.Null = true
	case *runtimev1.QueryScalar_StringValue:
		result.String = &arm.StringValue
	case *runtimev1.QueryScalar_BooleanValue:
		result.Boolean = &arm.BooleanValue
	case *runtimev1.QueryScalar_IntegerValue:
		result.Integer = &arm.IntegerValue
	case *runtimev1.QueryScalar_UnsignedValue:
		result.Unsigned = &arm.UnsignedValue
	case *runtimev1.QueryScalar_DoubleValue:
		result.Double = &arm.DoubleValue
	case *runtimev1.QueryScalar_DecimalValue:
		if arm.DecimalValue == nil {
			return result, queryInternal()
		}
		result.Decimal = &semantic.Decimal{Coefficient: arm.DecimalValue.GetCoefficient(), Scale: arm.DecimalValue.GetScale()}
	case *runtimev1.QueryScalar_DateValue:
		if arm.DateValue == nil {
			return result, queryInternal()
		}
		v := arm.DateValue.GetCalendarDate()
		result.Date = &v
	case *runtimev1.QueryScalar_DatetimeValue:
		if arm.DatetimeValue == nil {
			return result, queryInternal()
		}
		v := arm.DatetimeValue.GetUtcRfc3339()
		result.DateTime = &v
	default:
		return result, queryInternal()
	}
	return result, nil
}

func toWireQueryRecord(value semantic.Record) (*runtimev1.QueryRecord, error) {
	result := &runtimev1.QueryRecord{ObjectId: value.ObjectID}
	for _, field := range value.Fields {
		wireValue, err := toWireQueryValue(field.Value)
		if err != nil {
			return nil, err
		}
		result.Fields = append(result.Fields, &runtimev1.QueryField{Name: field.Name, Value: wireValue})
	}
	return result, nil
}
func fromWireQueryRecord(value *runtimev1.QueryRecord, depth int) (semantic.Record, error) {
	if depth > semantic.MaxNestingDepth {
		return semantic.Record{}, queryDepthExhausted()
	}
	if value == nil {
		return semantic.Record{}, queryInternal()
	}
	result := semantic.Record{ObjectID: value.GetObjectId()}
	for _, field := range value.GetFields() {
		if field == nil {
			return semantic.Record{}, queryInternal()
		}
		semanticValue, err := fromWireQueryValue(field.GetValue(), depth)
		if err != nil {
			return semantic.Record{}, err
		}
		result.Fields = append(result.Fields, semantic.Field{Name: field.GetName(), Value: semanticValue})
	}
	return result, nil
}

func toWireQueryValue(value semantic.Value) (*runtimev1.QueryValue, error) {
	result := &runtimev1.QueryValue{DeclaredKind: toWireQueryValueKind(value.Kind)}
	switch {
	case value.Null:
		result.Value = &runtimev1.QueryValue_NullValue{NullValue: &runtimev1.NullValue{}}
	case value.String != nil:
		result.Value = &runtimev1.QueryValue_StringValue{StringValue: *value.String}
	case value.Boolean != nil:
		result.Value = &runtimev1.QueryValue_BooleanValue{BooleanValue: *value.Boolean}
	case value.Integer != nil:
		result.Value = &runtimev1.QueryValue_IntegerValue{IntegerValue: *value.Integer}
	case value.Unsigned != nil:
		result.Value = &runtimev1.QueryValue_UnsignedValue{UnsignedValue: *value.Unsigned}
	case value.Double != nil:
		result.Value = &runtimev1.QueryValue_DoubleValue{DoubleValue: *value.Double}
	case value.Decimal != nil:
		result.Value = &runtimev1.QueryValue_DecimalValue{DecimalValue: &runtimev1.DecimalValue{Coefficient: value.Decimal.Coefficient, Scale: value.Decimal.Scale}}
	case value.Date != nil:
		result.Value = &runtimev1.QueryValue_DateValue{DateValue: &runtimev1.DateValue{CalendarDate: *value.Date}}
	case value.DateTime != nil:
		result.Value = &runtimev1.QueryValue_DatetimeValue{DatetimeValue: &runtimev1.DateTimeValue{UtcRfc3339: *value.DateTime}}
	case value.Reference != nil:
		result.Value = &runtimev1.QueryValue_ReferenceValue{ReferenceValue: &runtimev1.ReferenceValue{Identifier: *value.Reference}}
	case value.Object != nil:
		record, err := toWireQueryRecord(*value.Object)
		if err != nil {
			return nil, err
		}
		result.Value = &runtimev1.QueryValue_ObjectValue{ObjectValue: record}
	case value.List != nil:
		values := make([]*runtimev1.QueryValue, 0, len(*value.List))
		for _, item := range *value.List {
			wireItem, err := toWireQueryValue(item)
			if err != nil {
				return nil, err
			}
			values = append(values, wireItem)
		}
		result.Value = &runtimev1.QueryValue_ListValue{ListValue: &runtimev1.QueryValues{Values: values}}
	default:
		return nil, queryInternal()
	}
	return result, nil
}

func fromWireQueryValue(value *runtimev1.QueryValue, depth int) (semantic.Value, error) {
	if depth > semantic.MaxNestingDepth {
		return semantic.Value{}, queryDepthExhausted()
	}
	if value == nil {
		return semantic.Value{}, queryInternal()
	}
	result := semantic.Value{Kind: fromWireQueryValueKind(value.GetDeclaredKind())}
	switch arm := value.GetValue().(type) {
	case *runtimev1.QueryValue_NullValue:
		if arm.NullValue == nil {
			return result, queryInternal()
		}
		result.Null = true
	case *runtimev1.QueryValue_StringValue:
		result.String = &arm.StringValue
	case *runtimev1.QueryValue_BooleanValue:
		result.Boolean = &arm.BooleanValue
	case *runtimev1.QueryValue_IntegerValue:
		result.Integer = &arm.IntegerValue
	case *runtimev1.QueryValue_UnsignedValue:
		result.Unsigned = &arm.UnsignedValue
	case *runtimev1.QueryValue_DoubleValue:
		result.Double = &arm.DoubleValue
	case *runtimev1.QueryValue_DecimalValue:
		if arm.DecimalValue == nil {
			return result, queryInternal()
		}
		result.Decimal = &semantic.Decimal{Coefficient: arm.DecimalValue.GetCoefficient(), Scale: arm.DecimalValue.GetScale()}
	case *runtimev1.QueryValue_DateValue:
		if arm.DateValue == nil {
			return result, queryInternal()
		}
		v := arm.DateValue.GetCalendarDate()
		result.Date = &v
	case *runtimev1.QueryValue_DatetimeValue:
		if arm.DatetimeValue == nil {
			return result, queryInternal()
		}
		v := arm.DatetimeValue.GetUtcRfc3339()
		result.DateTime = &v
	case *runtimev1.QueryValue_ReferenceValue:
		if arm.ReferenceValue == nil {
			return result, queryInternal()
		}
		v := arm.ReferenceValue.GetIdentifier()
		result.Reference = &v
	case *runtimev1.QueryValue_ObjectValue:
		record, err := fromWireQueryRecord(arm.ObjectValue, depth+1)
		if err != nil {
			return result, err
		}
		result.Object = &record
	case *runtimev1.QueryValue_ListValue:
		if arm.ListValue == nil {
			return result, queryInternal()
		}
		values := make([]semantic.Value, 0, len(arm.ListValue.GetValues()))
		for _, item := range arm.ListValue.GetValues() {
			decoded, err := fromWireQueryValue(item, depth+1)
			if err != nil {
				return result, err
			}
			values = append(values, decoded)
		}
		result.List = &values
	default:
		return result, queryInternal()
	}
	return result, nil
}

func toWireQueryPredicateKind(value semantic.PredicateKind) runtimev1.QueryPredicateKind {
	return map[semantic.PredicateKind]runtimev1.QueryPredicateKind{semantic.PredicateAnd: runtimev1.QueryPredicateKind_QUERY_PREDICATE_KIND_AND, semantic.PredicateOr: runtimev1.QueryPredicateKind_QUERY_PREDICATE_KIND_OR, semantic.PredicateNot: runtimev1.QueryPredicateKind_QUERY_PREDICATE_KIND_NOT, semantic.PredicateExpression: runtimev1.QueryPredicateKind_QUERY_PREDICATE_KIND_EXPRESSION, semantic.PredicateComparison: runtimev1.QueryPredicateKind_QUERY_PREDICATE_KIND_COMPARISON, semantic.PredicateFieldComparison: runtimev1.QueryPredicateKind_QUERY_PREDICATE_KIND_FIELD_COMPARISON, semantic.PredicateCorrelatedMembership: runtimev1.QueryPredicateKind_QUERY_PREDICATE_KIND_CORRELATED_MEMBERSHIP}[value]
}
func fromWireQueryPredicateKind(value runtimev1.QueryPredicateKind) semantic.PredicateKind {
	return map[runtimev1.QueryPredicateKind]semantic.PredicateKind{runtimev1.QueryPredicateKind_QUERY_PREDICATE_KIND_AND: semantic.PredicateAnd, runtimev1.QueryPredicateKind_QUERY_PREDICATE_KIND_OR: semantic.PredicateOr, runtimev1.QueryPredicateKind_QUERY_PREDICATE_KIND_NOT: semantic.PredicateNot, runtimev1.QueryPredicateKind_QUERY_PREDICATE_KIND_EXPRESSION: semantic.PredicateExpression, runtimev1.QueryPredicateKind_QUERY_PREDICATE_KIND_COMPARISON: semantic.PredicateComparison, runtimev1.QueryPredicateKind_QUERY_PREDICATE_KIND_FIELD_COMPARISON: semantic.PredicateFieldComparison, runtimev1.QueryPredicateKind_QUERY_PREDICATE_KIND_CORRELATED_MEMBERSHIP: semantic.PredicateCorrelatedMembership}[value]
}
func toWireQueryOperandKind(value semantic.OperandKind) runtimev1.QueryOperandKind {
	return map[semantic.OperandKind]runtimev1.QueryOperandKind{semantic.OperandField: runtimev1.QueryOperandKind_QUERY_OPERAND_KIND_FIELD, semantic.OperandLiteral: runtimev1.QueryOperandKind_QUERY_OPERAND_KIND_LITERAL, semantic.OperandList: runtimev1.QueryOperandKind_QUERY_OPERAND_KIND_LIST, semantic.OperandFunction: runtimev1.QueryOperandKind_QUERY_OPERAND_KIND_FUNCTION, semantic.OperandTrustedContext: runtimev1.QueryOperandKind_QUERY_OPERAND_KIND_TRUSTED_CONTEXT}[value]
}
func fromWireQueryOperandKind(value runtimev1.QueryOperandKind) semantic.OperandKind {
	return map[runtimev1.QueryOperandKind]semantic.OperandKind{runtimev1.QueryOperandKind_QUERY_OPERAND_KIND_FIELD: semantic.OperandField, runtimev1.QueryOperandKind_QUERY_OPERAND_KIND_LITERAL: semantic.OperandLiteral, runtimev1.QueryOperandKind_QUERY_OPERAND_KIND_LIST: semantic.OperandList, runtimev1.QueryOperandKind_QUERY_OPERAND_KIND_FUNCTION: semantic.OperandFunction, runtimev1.QueryOperandKind_QUERY_OPERAND_KIND_TRUSTED_CONTEXT: semantic.OperandTrustedContext}[value]
}

func toWireQueryTrustedContext(value semantic.TrustedContextValue) runtimev1.QueryTrustedContextValue {
	return map[semantic.TrustedContextValue]runtimev1.QueryTrustedContextValue{
		semantic.TrustedContextPrincipalID: runtimev1.QueryTrustedContextValue_QUERY_TRUSTED_CONTEXT_VALUE_PRINCIPAL_ID,
	}[value]
}

func fromWireQueryTrustedContext(value runtimev1.QueryTrustedContextValue) (semantic.TrustedContextValue, bool) {
	for semanticValue, wireValue := range map[semantic.TrustedContextValue]runtimev1.QueryTrustedContextValue{
		semantic.TrustedContextPrincipalID: runtimev1.QueryTrustedContextValue_QUERY_TRUSTED_CONTEXT_VALUE_PRINCIPAL_ID,
	} {
		if value == wireValue {
			return semanticValue, true
		}
	}
	return "", false
}

var queryComparisonOperatorToWire = map[semantic.ComparisonOperator]runtimev1.QueryComparisonOperator{
	semantic.ComparisonEqual:          runtimev1.QueryComparisonOperator_QUERY_COMPARISON_OPERATOR_EQUAL,
	semantic.ComparisonNotEqual:       runtimev1.QueryComparisonOperator_QUERY_COMPARISON_OPERATOR_NOT_EQUAL,
	semantic.ComparisonGreaterThan:    runtimev1.QueryComparisonOperator_QUERY_COMPARISON_OPERATOR_GREATER_THAN,
	semantic.ComparisonGreaterOrEqual: runtimev1.QueryComparisonOperator_QUERY_COMPARISON_OPERATOR_GREATER_OR_EQUAL,
	semantic.ComparisonLessThan:       runtimev1.QueryComparisonOperator_QUERY_COMPARISON_OPERATOR_LESS_THAN,
	semantic.ComparisonLessOrEqual:    runtimev1.QueryComparisonOperator_QUERY_COMPARISON_OPERATOR_LESS_OR_EQUAL,
	semantic.ComparisonIn:             runtimev1.QueryComparisonOperator_QUERY_COMPARISON_OPERATOR_IN,
	semantic.ComparisonNotIn:          runtimev1.QueryComparisonOperator_QUERY_COMPARISON_OPERATOR_NOT_IN,
	semantic.ComparisonContains:       runtimev1.QueryComparisonOperator_QUERY_COMPARISON_OPERATOR_CONTAINS,
	semantic.ComparisonStartsWith:     runtimev1.QueryComparisonOperator_QUERY_COMPARISON_OPERATOR_STARTS_WITH,
	semantic.ComparisonEndsWith:       runtimev1.QueryComparisonOperator_QUERY_COMPARISON_OPERATOR_ENDS_WITH,
	semantic.ComparisonLike:           runtimev1.QueryComparisonOperator_QUERY_COMPARISON_OPERATOR_LIKE,
	semantic.ComparisonNotLike:        runtimev1.QueryComparisonOperator_QUERY_COMPARISON_OPERATOR_NOT_LIKE,
}

func toWireQueryComparisonOperator(value semantic.ComparisonOperator) runtimev1.QueryComparisonOperator {
	return queryComparisonOperatorToWire[value]
}
func fromWireQueryComparisonOperator(value runtimev1.QueryComparisonOperator) (semantic.ComparisonOperator, bool) {
	for semanticValue, wireValue := range queryComparisonOperatorToWire {
		if value == wireValue {
			return semanticValue, true
		}
	}
	return "", false
}

var queryFunctionToWire = map[semantic.Function]runtimev1.QueryFunctionName{
	semantic.FunctionCount:             runtimev1.QueryFunctionName_QUERY_FUNCTION_NAME_COUNT,
	semantic.FunctionCountDistinct:     runtimev1.QueryFunctionName_QUERY_FUNCTION_NAME_COUNT_DISTINCT,
	semantic.FunctionSum:               runtimev1.QueryFunctionName_QUERY_FUNCTION_NAME_SUM,
	semantic.FunctionAverage:           runtimev1.QueryFunctionName_QUERY_FUNCTION_NAME_AVG,
	semantic.FunctionMinimum:           runtimev1.QueryFunctionName_QUERY_FUNCTION_NAME_MIN,
	semantic.FunctionMaximum:           runtimev1.QueryFunctionName_QUERY_FUNCTION_NAME_MAX,
	semantic.FunctionString:            runtimev1.QueryFunctionName_QUERY_FUNCTION_NAME_STRING,
	semantic.FunctionFormat:            runtimev1.QueryFunctionName_QUERY_FUNCTION_NAME_FORMAT,
	semantic.FunctionDisplayValue:      runtimev1.QueryFunctionName_QUERY_FUNCTION_NAME_DISPLAY_VALUE,
	semantic.FunctionNormalizeCurrency: runtimev1.QueryFunctionName_QUERY_FUNCTION_NAME_NORMALIZE_CURRENCY,
	semantic.FunctionGrouping:          runtimev1.QueryFunctionName_QUERY_FUNCTION_NAME_GROUPING,
	semantic.FunctionTemporalPart:      runtimev1.QueryFunctionName_QUERY_FUNCTION_NAME_TEMPORAL_PART,
	semantic.FunctionGeoDistance:       runtimev1.QueryFunctionName_QUERY_FUNCTION_NAME_GEO_DISTANCE,
	semantic.FunctionGeoPoint:          runtimev1.QueryFunctionName_QUERY_FUNCTION_NAME_GEO_POINT,
}

func toWireQueryFunction(value semantic.Function) runtimev1.QueryFunctionName {
	return queryFunctionToWire[value]
}
func fromWireQueryFunction(value runtimev1.QueryFunctionName) (semantic.Function, bool) {
	for semanticValue, wireValue := range queryFunctionToWire {
		if value == wireValue {
			return semanticValue, true
		}
	}
	return "", false
}

var queryTemporalPartToWire = map[semantic.TemporalPart]runtimev1.QueryTemporalPart{
	semantic.TemporalPartMonth:       runtimev1.QueryTemporalPart_QUERY_TEMPORAL_PART_MONTH,
	semantic.TemporalPartYear:        runtimev1.QueryTemporalPart_QUERY_TEMPORAL_PART_YEAR,
	semantic.TemporalPartQuarter:     runtimev1.QueryTemporalPart_QUERY_TEMPORAL_PART_QUARTER,
	semantic.TemporalPartDayOfMonth:  runtimev1.QueryTemporalPart_QUERY_TEMPORAL_PART_DAY_OF_MONTH,
	semantic.TemporalPartDayOfWeek:   runtimev1.QueryTemporalPart_QUERY_TEMPORAL_PART_DAY_OF_WEEK,
	semantic.TemporalPartDayOfYear:   runtimev1.QueryTemporalPart_QUERY_TEMPORAL_PART_DAY_OF_YEAR,
	semantic.TemporalPartDate:        runtimev1.QueryTemporalPart_QUERY_TEMPORAL_PART_DATE,
	semantic.TemporalPartHour:        runtimev1.QueryTemporalPart_QUERY_TEMPORAL_PART_HOUR,
	semantic.TemporalPartWeekOfMonth: runtimev1.QueryTemporalPart_QUERY_TEMPORAL_PART_WEEK_OF_MONTH,
	semantic.TemporalPartWeekOfYear:  runtimev1.QueryTemporalPart_QUERY_TEMPORAL_PART_WEEK_OF_YEAR,
}

func toWireQueryTemporalPart(value semantic.TemporalPart) runtimev1.QueryTemporalPart {
	return queryTemporalPartToWire[value]
}
func fromWireQueryTemporalPart(value runtimev1.QueryTemporalPart) (semantic.TemporalPart, bool) {
	if value == runtimev1.QueryTemporalPart_QUERY_TEMPORAL_PART_UNSPECIFIED {
		return "", true
	}
	for semanticValue, wireValue := range queryTemporalPartToWire {
		if value == wireValue {
			return semanticValue, true
		}
	}
	return "", false
}

func toWireQueryTemporalBasis(value semantic.TemporalBasis) runtimev1.QueryTemporalBasis {
	switch value {
	case semantic.TemporalBasisCivil:
		return runtimev1.QueryTemporalBasis_QUERY_TEMPORAL_BASIS_CIVIL
	case semantic.TemporalBasisBusiness:
		return runtimev1.QueryTemporalBasis_QUERY_TEMPORAL_BASIS_BUSINESS
	default:
		return runtimev1.QueryTemporalBasis_QUERY_TEMPORAL_BASIS_UNSPECIFIED
	}
}
func fromWireQueryTemporalBasis(value runtimev1.QueryTemporalBasis) (semantic.TemporalBasis, bool) {
	switch value {
	case runtimev1.QueryTemporalBasis_QUERY_TEMPORAL_BASIS_UNSPECIFIED:
		return "", true
	case runtimev1.QueryTemporalBasis_QUERY_TEMPORAL_BASIS_CIVIL:
		return semantic.TemporalBasisCivil, true
	case runtimev1.QueryTemporalBasis_QUERY_TEMPORAL_BASIS_BUSINESS:
		return semantic.TemporalBasisBusiness, true
	default:
		return "", false
	}
}

func toWireQueryDistanceUnit(value semantic.DistanceUnit) runtimev1.QueryDistanceUnit {
	switch value {
	case semantic.DistanceUnitKilometers:
		return runtimev1.QueryDistanceUnit_QUERY_DISTANCE_UNIT_KILOMETERS
	case semantic.DistanceUnitMiles:
		return runtimev1.QueryDistanceUnit_QUERY_DISTANCE_UNIT_MILES
	default:
		return runtimev1.QueryDistanceUnit_QUERY_DISTANCE_UNIT_UNSPECIFIED
	}
}
func fromWireQueryDistanceUnit(value runtimev1.QueryDistanceUnit) (semantic.DistanceUnit, bool) {
	switch value {
	case runtimev1.QueryDistanceUnit_QUERY_DISTANCE_UNIT_UNSPECIFIED:
		return "", true
	case runtimev1.QueryDistanceUnit_QUERY_DISTANCE_UNIT_KILOMETERS:
		return semantic.DistanceUnitKilometers, true
	case runtimev1.QueryDistanceUnit_QUERY_DISTANCE_UNIT_MILES:
		return semantic.DistanceUnitMiles, true
	default:
		return "", false
	}
}

func toWireQuerySortDirection(value semantic.SortDirection) runtimev1.QuerySortDirection {
	switch value {
	case semantic.SortAscending:
		return runtimev1.QuerySortDirection_QUERY_SORT_DIRECTION_ASCENDING
	case semantic.SortDescending:
		return runtimev1.QuerySortDirection_QUERY_SORT_DIRECTION_DESCENDING
	default:
		return runtimev1.QuerySortDirection_QUERY_SORT_DIRECTION_UNSPECIFIED
	}
}
func fromWireQuerySortDirection(value runtimev1.QuerySortDirection) (semantic.SortDirection, bool) {
	switch value {
	case runtimev1.QuerySortDirection_QUERY_SORT_DIRECTION_ASCENDING:
		return semantic.SortAscending, true
	case runtimev1.QuerySortDirection_QUERY_SORT_DIRECTION_DESCENDING:
		return semantic.SortDescending, true
	default:
		return "", false
	}
}

func toWireQuerySelectionKind(value semantic.SelectionKind) runtimev1.QuerySelectionKind {
	switch value {
	case semantic.SelectionField:
		return runtimev1.QuerySelectionKind_QUERY_SELECTION_KIND_FIELD
	case semantic.SelectionAggregate:
		return runtimev1.QuerySelectionKind_QUERY_SELECTION_KIND_AGGREGATE
	default:
		return runtimev1.QuerySelectionKind_QUERY_SELECTION_KIND_UNSPECIFIED
	}
}
func fromWireQuerySelectionKind(value runtimev1.QuerySelectionKind) (semantic.SelectionKind, bool) {
	switch value {
	case runtimev1.QuerySelectionKind_QUERY_SELECTION_KIND_FIELD:
		return semantic.SelectionField, true
	case runtimev1.QuerySelectionKind_QUERY_SELECTION_KIND_AGGREGATE:
		return semantic.SelectionAggregate, true
	default:
		return "", false
	}
}

func toWireQueryAggregateFunction(value semantic.AggregateFunction) runtimev1.QueryAggregateFunction {
	switch value {
	case semantic.AggregateCount:
		return runtimev1.QueryAggregateFunction_QUERY_AGGREGATE_FUNCTION_COUNT
	case semantic.AggregateSum:
		return runtimev1.QueryAggregateFunction_QUERY_AGGREGATE_FUNCTION_SUM
	case semantic.AggregateAverage:
		return runtimev1.QueryAggregateFunction_QUERY_AGGREGATE_FUNCTION_AVG
	case semantic.AggregateMinimum:
		return runtimev1.QueryAggregateFunction_QUERY_AGGREGATE_FUNCTION_MIN
	case semantic.AggregateMaximum:
		return runtimev1.QueryAggregateFunction_QUERY_AGGREGATE_FUNCTION_MAX
	default:
		return runtimev1.QueryAggregateFunction_QUERY_AGGREGATE_FUNCTION_UNSPECIFIED
	}
}
func fromWireQueryAggregateFunction(value runtimev1.QueryAggregateFunction) (semantic.AggregateFunction, bool) {
	switch value {
	case runtimev1.QueryAggregateFunction_QUERY_AGGREGATE_FUNCTION_UNSPECIFIED:
		return "", true
	case runtimev1.QueryAggregateFunction_QUERY_AGGREGATE_FUNCTION_COUNT:
		return semantic.AggregateCount, true
	case runtimev1.QueryAggregateFunction_QUERY_AGGREGATE_FUNCTION_SUM:
		return semantic.AggregateSum, true
	case runtimev1.QueryAggregateFunction_QUERY_AGGREGATE_FUNCTION_AVG:
		return semantic.AggregateAverage, true
	case runtimev1.QueryAggregateFunction_QUERY_AGGREGATE_FUNCTION_MIN:
		return semantic.AggregateMinimum, true
	case runtimev1.QueryAggregateFunction_QUERY_AGGREGATE_FUNCTION_MAX:
		return semantic.AggregateMaximum, true
	default:
		return "", false
	}
}

// queryDecodeBudget enforces the semantic query tree ceilings while the
// untrusted protobuf graph is being decoded. Validation after conversion is
// still required for shape and identifier rules, but it is deliberately not
// the first resource boundary: recursive descent never proceeds beyond the
// approved depth or aggregate predicate/operand node count.
type queryDecodeBudget struct {
	nodes int
}

func (budget *queryDecodeBudget) enter(depth int) error {
	if depth > semantic.MaxNestingDepth {
		return queryDepthExhausted()
	}
	budget.nodes++
	if budget.nodes > semantic.MaxPredicateNodes {
		return &semantic.Failure{
			Category:  semantic.FailureResourceExhausted,
			LimitKind: semantic.LimitQueryPredicate,
			Maximum:   uint64(semantic.MaxPredicateNodes),
		}
	}
	return nil
}

func toWireQueryValueKind(value semantic.ValueKind) runtimev1.QueryValueKind {
	return map[semantic.ValueKind]runtimev1.QueryValueKind{semantic.ValueString: runtimev1.QueryValueKind_QUERY_VALUE_KIND_STRING, semantic.ValueBoolean: runtimev1.QueryValueKind_QUERY_VALUE_KIND_BOOLEAN, semantic.ValueInteger: runtimev1.QueryValueKind_QUERY_VALUE_KIND_INTEGER, semantic.ValueUnsigned: runtimev1.QueryValueKind_QUERY_VALUE_KIND_UNSIGNED, semantic.ValueDouble: runtimev1.QueryValueKind_QUERY_VALUE_KIND_DOUBLE, semantic.ValueDecimal: runtimev1.QueryValueKind_QUERY_VALUE_KIND_DECIMAL, semantic.ValueDate: runtimev1.QueryValueKind_QUERY_VALUE_KIND_DATE, semantic.ValueDateTime: runtimev1.QueryValueKind_QUERY_VALUE_KIND_DATETIME, semantic.ValueReference: runtimev1.QueryValueKind_QUERY_VALUE_KIND_REFERENCE, semantic.ValueObject: runtimev1.QueryValueKind_QUERY_VALUE_KIND_OBJECT, semantic.ValueList: runtimev1.QueryValueKind_QUERY_VALUE_KIND_LIST}[value]
}
func fromWireQueryValueKind(value runtimev1.QueryValueKind) semantic.ValueKind {
	return map[runtimev1.QueryValueKind]semantic.ValueKind{runtimev1.QueryValueKind_QUERY_VALUE_KIND_STRING: semantic.ValueString, runtimev1.QueryValueKind_QUERY_VALUE_KIND_BOOLEAN: semantic.ValueBoolean, runtimev1.QueryValueKind_QUERY_VALUE_KIND_INTEGER: semantic.ValueInteger, runtimev1.QueryValueKind_QUERY_VALUE_KIND_UNSIGNED: semantic.ValueUnsigned, runtimev1.QueryValueKind_QUERY_VALUE_KIND_DOUBLE: semantic.ValueDouble, runtimev1.QueryValueKind_QUERY_VALUE_KIND_DECIMAL: semantic.ValueDecimal, runtimev1.QueryValueKind_QUERY_VALUE_KIND_DATE: semantic.ValueDate, runtimev1.QueryValueKind_QUERY_VALUE_KIND_DATETIME: semantic.ValueDateTime, runtimev1.QueryValueKind_QUERY_VALUE_KIND_REFERENCE: semantic.ValueReference, runtimev1.QueryValueKind_QUERY_VALUE_KIND_OBJECT: semantic.ValueObject, runtimev1.QueryValueKind_QUERY_VALUE_KIND_LIST: semantic.ValueList}[value]
}

func queryIncompatible() *semantic.Failure {
	return &semantic.Failure{Category: semantic.FailureIncompatible, RequiredCapability: semantic.CapabilityName, SupportedMajor: semantic.ProtocolMajor, SupportedMinorMin: semantic.ProtocolMinor, SupportedMinorMax: semantic.ProtocolMinor}
}
func queryDepthExhausted() *semantic.Failure {
	return &semantic.Failure{Category: semantic.FailureResourceExhausted, LimitKind: semantic.LimitQueryDepth, Maximum: uint64(semantic.MaxNestingDepth)}
}
func queryInternal() *semantic.Failure { return &semantic.Failure{Category: semantic.FailureInternal} }
