// Code generated by go-swagger; DO NOT EDIT.

package models

// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command

import (
	"context"
	"encoding/json"
	"strconv"

	"github.com/go-openapi/errors"
	"github.com/go-openapi/strfmt"
	"github.com/go-openapi/swag"
	"github.com/go-openapi/validate"
)

// Span Span
//
// swagger:model Span
type Span struct {

	// Associates events that explain latency with the time they happened.
	// Unique: true
	Annotations []*Annotation `json:"annotations"`

	// True is a request to store this span even if it overrides sampling policy.
	//
	// This is true when the `X-B3-Flags` header has a value of 1.
	//
	Debug bool `json:"debug,omitempty"`

	// Duration in **microseconds** of the critical path, if known. Durations of less
	// than one are rounded up. Duration of children can be longer than their parents
	// due to asynchronous operations.
	//
	// For example 150 milliseconds is 150000 microseconds.
	//
	// Minimum: 1
	Duration int64 `json:"duration,omitempty"`

	// Unique 64bit identifier for this operation within the trace.
	//
	// Encoded as 16 lowercase hex characters. For example ffdc9bb9a6453df3
	//
	// Required: true
	// Max Length: 16
	// Min Length: 16
	// Pattern: [a-z0-9]{16}
	ID *string `json:"id"`

	// When present, clarifies timestamp, duration and remoteEndpoint. When
	// absent, the span is local or incomplete. Unlike client and server,
	// there is no direct critical path latency relationship between producer
	// and consumer spans.
	//
	// * `CLIENT`
	//   * timestamp - The moment a request was sent (formerly "cs")
	//   * duration - When present indicates when a response was received (formerly "cr")
	//   * remoteEndpoint - Represents the server. Leave serviceName absent if unknown.
	// * `SERVER`
	//   * timestamp - The moment a request was received (formerly "sr")
	//   * duration - When present indicates when a response was sent (formerly "ss")
	//   * remoteEndpoint - Represents the client. Leave serviceName absent if unknown.
	// * `PRODUCER`
	//   * timestamp - The moment a message was sent to a destination (formerly "ms")
	//   * duration - When present represents delay sending the message, such as batching.
	//   * remoteEndpoint - Represents the broker. Leave serviceName absent if unknown.
	// * `CONSUMER`
	//   * timestamp - The moment a message was received from an origin (formerly "mr")
	//   * duration - When present represents delay consuming the message, such as from backlog.
	//   * remoteEndpoint - Represents the broker. Leave serviceName absent if unknown.
	//
	// Enum: [CLIENT SERVER PRODUCER CONSUMER]
	Kind string `json:"kind,omitempty"`

	// The host that recorded this span, primarily for query by service name.
	//
	// Instrumentation should always record this. Usually, absent implies late data.
	// The IP address corresponding to this is usually the site local or advertised
	// service address. When present, the port indicates the listen port.
	//
	LocalEndpoint *Endpoint `json:"localEndpoint,omitempty"`

	// The logical operation this span represents in lowercase (e.g. rpc method).
	// Leave absent if unknown.
	//
	// As these are lookup labels, take care to ensure names are low cardinality.
	// For example, do not embed variables into the name.
	//
	Name string `json:"name,omitempty"`

	// The parent span ID or absent if this the root span in a trace.
	// Max Length: 16
	// Min Length: 16
	// Pattern: [a-z0-9]{16}
	ParentID string `json:"parentId,omitempty"`

	// When an RPC (or messaging) span, indicates the other side of the connection.
	//
	RemoteEndpoint *Endpoint `json:"remoteEndpoint,omitempty"`

	// True if we are contributing to a span started by another tracer (ex on a different host).
	Shared bool `json:"shared,omitempty"`

	// Tags give your span context for search, viewing and analysis.
	Tags Tags `json:"tags,omitempty"`

	// Epoch **microseconds** of the start of this span, possibly absent if incomplete.
	//
	// For example, 1502787600000000 corresponds to 2017-08-15 09:00 UTC
	//
	// This value should be set directly by instrumentation, using the most precise
	// value possible. For example, gettimeofday or multiplying epoch millis by 1000.
	//
	// There are three known edge-cases where this could be reported absent.
	//  * A span was allocated but never started (ex not yet received a timestamp)
	//  * The span's start event was lost
	//  * Data about a completed span (ex tags) were sent after the fact
	//
	Timestamp int64 `json:"timestamp,omitempty"`

	// Randomly generated, unique identifier for a trace, set on all spans within it.
	//
	// Encoded as 16 or 32 lowercase hex characters corresponding to 64 or 128 bits.
	// For example, a 128bit trace ID looks like 4e441824ec2b6a44ffdc9bb9a6453df3
	//
	// Required: true
	// Max Length: 32
	// Min Length: 16
	// Pattern: [a-z0-9]{16,32}
	TraceID *string `json:"traceId"`
}

// Validate validates this span
func (m *Span) Validate(formats strfmt.Registry) error {
	var res []error

	if err := m.validateAnnotations(formats); err != nil {
		res = append(res, err)
	}

	if err := m.validateDuration(formats); err != nil {
		res = append(res, err)
	}

	if err := m.validateID(formats); err != nil {
		res = append(res, err)
	}

	if err := m.validateKind(formats); err != nil {
		res = append(res, err)
	}

	if err := m.validateLocalEndpoint(formats); err != nil {
		res = append(res, err)
	}

	if err := m.validateParentID(formats); err != nil {
		res = append(res, err)
	}

	if err := m.validateRemoteEndpoint(formats); err != nil {
		res = append(res, err)
	}

	if err := m.validateTags(formats); err != nil {
		res = append(res, err)
	}

	if err := m.validateTraceID(formats); err != nil {
		res = append(res, err)
	}

	if len(res) > 0 {
		return errors.CompositeValidationError(res...)
	}
	return nil
}

func (m *Span) validateAnnotations(formats strfmt.Registry) error {
	if swag.IsZero(m.Annotations) { // not required
		return nil
	}

	if err := validate.UniqueItems("annotations", "body", m.Annotations); err != nil {
		return err
	}

	for i := 0; i < len(m.Annotations); i++ {
		if swag.IsZero(m.Annotations[i]) { // not required
			continue
		}

		if m.Annotations[i] != nil {
			if err := m.Annotations[i].Validate(formats); err != nil {
				if ve, ok := err.(*errors.Validation); ok {
					return ve.ValidateName("annotations" + "." + strconv.Itoa(i))
				}
				return err
			}
		}

	}

	return nil
}

func (m *Span) validateDuration(formats strfmt.Registry) error {
	if swag.IsZero(m.Duration) { // not required
		return nil
	}

	if err := validate.MinimumInt("duration", "body", m.Duration, 1, false); err != nil {
		return err
	}

	return nil
}

func (m *Span) validateID(formats strfmt.Registry) error {

	if err := validate.Required("id", "body", m.ID); err != nil {
		return err
	}

	if err := validate.MinLength("id", "body", *m.ID, 16); err != nil {
		return err
	}

	if err := validate.MaxLength("id", "body", *m.ID, 16); err != nil {
		return err
	}

	if err := validate.Pattern("id", "body", *m.ID, `[a-z0-9]{16}`); err != nil {
		return err
	}

	return nil
}

var spanTypeKindPropEnum []interface{}

func init() {
	var res []string
	if err := json.Unmarshal([]byte(`["CLIENT","SERVER","PRODUCER","CONSUMER"]`), &res); err != nil {
		panic(err)
	}
	for _, v := range res {
		spanTypeKindPropEnum = append(spanTypeKindPropEnum, v)
	}
}

const (

	// SpanKindCLIENT captures enum value "CLIENT"
	SpanKindCLIENT string = "CLIENT"

	// SpanKindSERVER captures enum value "SERVER"
	SpanKindSERVER string = "SERVER"

	// SpanKindPRODUCER captures enum value "PRODUCER"
	SpanKindPRODUCER string = "PRODUCER"

	// SpanKindCONSUMER captures enum value "CONSUMER"
	SpanKindCONSUMER string = "CONSUMER"
)

// prop value enum
func (m *Span) validateKindEnum(path, location string, value string) error {
	if err := validate.EnumCase(path, location, value, spanTypeKindPropEnum, true); err != nil {
		return err
	}
	return nil
}

func (m *Span) validateKind(formats strfmt.Registry) error {
	if swag.IsZero(m.Kind) { // not required
		return nil
	}

	// value enum
	if err := m.validateKindEnum("kind", "body", m.Kind); err != nil {
		return err
	}

	return nil
}

func (m *Span) validateLocalEndpoint(formats strfmt.Registry) error {
	if swag.IsZero(m.LocalEndpoint) { // not required
		return nil
	}

	if m.LocalEndpoint != nil {
		if err := m.LocalEndpoint.Validate(formats); err != nil {
			if ve, ok := err.(*errors.Validation); ok {
				return ve.ValidateName("localEndpoint")
			}
			return err
		}
	}

	return nil
}

func (m *Span) validateParentID(formats strfmt.Registry) error {
	if swag.IsZero(m.ParentID) { // not required
		return nil
	}

	if err := validate.MinLength("parentId", "body", m.ParentID, 16); err != nil {
		return err
	}

	if err := validate.MaxLength("parentId", "body", m.ParentID, 16); err != nil {
		return err
	}

	if err := validate.Pattern("parentId", "body", m.ParentID, `[a-z0-9]{16}`); err != nil {
		return err
	}

	return nil
}

func (m *Span) validateRemoteEndpoint(formats strfmt.Registry) error {
	if swag.IsZero(m.RemoteEndpoint) { // not required
		return nil
	}

	if m.RemoteEndpoint != nil {
		if err := m.RemoteEndpoint.Validate(formats); err != nil {
			if ve, ok := err.(*errors.Validation); ok {
				return ve.ValidateName("remoteEndpoint")
			}
			return err
		}
	}

	return nil
}

func (m *Span) validateTags(formats strfmt.Registry) error {
	if swag.IsZero(m.Tags) { // not required
		return nil
	}

	if m.Tags != nil {
		if err := m.Tags.Validate(formats); err != nil {
			if ve, ok := err.(*errors.Validation); ok {
				return ve.ValidateName("tags")
			}
			return err
		}
	}

	return nil
}

func (m *Span) validateTraceID(formats strfmt.Registry) error {

	if err := validate.Required("traceId", "body", m.TraceID); err != nil {
		return err
	}

	if err := validate.MinLength("traceId", "body", *m.TraceID, 16); err != nil {
		return err
	}

	if err := validate.MaxLength("traceId", "body", *m.TraceID, 32); err != nil {
		return err
	}

	if err := validate.Pattern("traceId", "body", *m.TraceID, `[a-z0-9]{16,32}`); err != nil {
		return err
	}

	return nil
}

// ContextValidate validate this span based on the context it is used
func (m *Span) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
	var res []error

	if err := m.contextValidateAnnotations(ctx, formats); err != nil {
		res = append(res, err)
	}

	if err := m.contextValidateLocalEndpoint(ctx, formats); err != nil {
		res = append(res, err)
	}

	if err := m.contextValidateRemoteEndpoint(ctx, formats); err != nil {
		res = append(res, err)
	}

	if err := m.contextValidateTags(ctx, formats); err != nil {
		res = append(res, err)
	}

	if len(res) > 0 {
		return errors.CompositeValidationError(res...)
	}
	return nil
}

func (m *Span) contextValidateAnnotations(ctx context.Context, formats strfmt.Registry) error {

	for i := 0; i < len(m.Annotations); i++ {

		if m.Annotations[i] != nil {
			if err := m.Annotations[i].ContextValidate(ctx, formats); err != nil {
				if ve, ok := err.(*errors.Validation); ok {
					return ve.ValidateName("annotations" + "." + strconv.Itoa(i))
				}
				return err
			}
		}

	}

	return nil
}

func (m *Span) contextValidateLocalEndpoint(ctx context.Context, formats strfmt.Registry) error {

	if m.LocalEndpoint != nil {
		if err := m.LocalEndpoint.ContextValidate(ctx, formats); err != nil {
			if ve, ok := err.(*errors.Validation); ok {
				return ve.ValidateName("localEndpoint")
			}
			return err
		}
	}

	return nil
}

func (m *Span) contextValidateRemoteEndpoint(ctx context.Context, formats strfmt.Registry) error {

	if m.RemoteEndpoint != nil {
		if err := m.RemoteEndpoint.ContextValidate(ctx, formats); err != nil {
			if ve, ok := err.(*errors.Validation); ok {
				return ve.ValidateName("remoteEndpoint")
			}
			return err
		}
	}

	return nil
}

func (m *Span) contextValidateTags(ctx context.Context, formats strfmt.Registry) error {

	if err := m.Tags.ContextValidate(ctx, formats); err != nil {
		if ve, ok := err.(*errors.Validation); ok {
			return ve.ValidateName("tags")
		}
		return err
	}

	return nil
}

// MarshalBinary interface implementation
func (m *Span) MarshalBinary() ([]byte, error) {
	if m == nil {
		return nil, nil
	}
	return swag.WriteJSON(m)
}

// UnmarshalBinary interface implementation
func (m *Span) UnmarshalBinary(b []byte) error {
	var res Span
	if err := swag.ReadJSON(b, &res); err != nil {
		return err
	}
	*m = res
	return nil
}
