// SPDX-License-Identifier: Apache-2.0
// Copyright Authors of Cilium

// Copyright 2015 The Kubernetes Authors.

package v1

import (
	"time"
)

// Timestamp is a struct that is equivalent to Time, but intended for
// protobuf marshalling/unmarshalling. It is generated into a serialization
// that matches Time. Do not use in Go structs.
type Timestamp struct {
	// Represents seconds of UTC time since Unix epoch
	// 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
	// 9999-12-31T23:59:59Z inclusive.
	Seconds int64 `json:"seconds" protobuf:"varint,1,opt,name=seconds"`
	// Non-negative fractions of a second at nanosecond resolution. Negative
	// second values with fractions must still have non-negative nanos values
	// that count forward in time. Must be from 0 to 999,999,999
	// inclusive. This field may be limited in precision depending on context.
	Nanos int32 `json:"nanos" protobuf:"varint,2,opt,name=nanos"`
}

// Timestamp returns the Time as a new Timestamp value.
func (m *Time) ProtoTime() *Timestamp {
	if m == nil {
		return &Timestamp{}
	}
	return &Timestamp{
		Seconds: m.Time.Unix(),
		// leaving this here for the record.  our JSON only handled seconds, so this results in writes by
		// protobuf clients storing values that aren't read by json clients, which results in unexpected
		// field mutation, which fails various validation and equality code.
		// Nanos:   int32(m.Time.Nanosecond()),
	}
}

// Size implements the protobuf marshalling interface.
func (m *Time) Size() (n int) {
	if m == nil || m.Time.IsZero() {
		return 0
	}
	return m.ProtoTime().Size()
}

// Reset implements the protobuf marshalling interface.
func (m *Time) Unmarshal(data []byte) error {
	if len(data) == 0 {
		m.Time = time.Time{}
		return nil
	}
	p := Timestamp{}
	if err := p.Unmarshal(data); err != nil {
		return err
	}
	// leaving this here for the record.  our JSON only handled seconds, so this results in writes by
	// protobuf clients storing values that aren't read by json clients, which results in unexpected
	// field mutation, which fails various validation and equality code.
	// m.Time = time.Unix(p.Seconds, int64(p.Nanos)).Local()
	m.Time = time.Unix(p.Seconds, int64(0)).Local()
	return nil
}

// Marshal implements the protobuf marshaling interface.
func (m *Time) Marshal() (data []byte, err error) {
	if m == nil || m.Time.IsZero() {
		return nil, nil
	}
	return m.ProtoTime().Marshal()
}

// MarshalTo implements the protobuf marshaling interface.
func (m *Time) MarshalTo(data []byte) (int, error) {
	if m == nil || m.Time.IsZero() {
		return 0, nil
	}
	return m.ProtoTime().MarshalTo(data)
}

// MarshalToSizedBuffer implements the protobuf reverse marshaling interface.
func (m *Time) MarshalToSizedBuffer(data []byte) (int, error) {
	if m == nil || m.Time.IsZero() {
		return 0, nil
	}
	return m.ProtoTime().MarshalToSizedBuffer(data)
}
