// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
// SPDX-License-Identifier: MIT

package rtp

import (
	
	
)

const (
	absCaptureTimeExtensionSize         = 8
	absCaptureTimeExtendedExtensionSize = 16
)

// AbsCaptureTimeExtension is a extension payload format in.
// http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time
// 0                   1                   2                   3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// |  ID   | len=7 |     absolute capture timestamp (bit 0-23)     |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// |             absolute capture timestamp (bit 24-55)            |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// |  ... (56-63)  |
// +-+-+-+-+-+-+-+-+
// .
type AbsCaptureTimeExtension struct {
	Timestamp                   uint64
	EstimatedCaptureClockOffset *int64
}

// Marshal serializes the members to buffer.
func ( AbsCaptureTimeExtension) () ([]byte, error) {
	if .EstimatedCaptureClockOffset != nil {
		 := make([]byte, 16)
		binary.BigEndian.PutUint64([0:8], .Timestamp)
		binary.BigEndian.PutUint64([8:16], uint64(*.EstimatedCaptureClockOffset)) // nolint: gosec // G115

		return , nil
	}
	 := make([]byte, 8)
	binary.BigEndian.PutUint64([0:8], .Timestamp)

	return , nil
}

// Unmarshal parses the passed byte slice and stores the result in the members.
func ( *AbsCaptureTimeExtension) ( []byte) error {
	if len() < absCaptureTimeExtensionSize {
		return errTooSmall
	}
	.Timestamp = binary.BigEndian.Uint64([0:8])
	if len() >= absCaptureTimeExtendedExtensionSize {
		 := int64(binary.BigEndian.Uint64([8:16])) // nolint: gosec // G115 false positive
		.EstimatedCaptureClockOffset = &
	}

	return nil
}

// CaptureTime produces the estimated time.Time represented by this extension.
func ( AbsCaptureTimeExtension) () time.Time {
	return toTime(.Timestamp)
}

// EstimatedCaptureClockOffsetDuration produces the estimated time.Duration represented by this extension.
func ( AbsCaptureTimeExtension) () *time.Duration {
	if .EstimatedCaptureClockOffset == nil {
		return nil
	}
	 := *.EstimatedCaptureClockOffset
	 := false
	if  < 0 {
		 = -
		 = true
	}
	 := time.Duration(/(1<<32))*time.Second + time.Duration((&0xFFFFFFFF)*1e9/(1<<32))*time.Nanosecond
	if  {
		 = -
	}

	return &
}

// NewAbsCaptureTimeExtension makes new AbsCaptureTimeExtension from time.Time.
func ( time.Time) *AbsCaptureTimeExtension {
	return &AbsCaptureTimeExtension{
		Timestamp: toNtpTime(),
	}
}

// NewAbsCaptureTimeExtensionWithCaptureClockOffset makes new AbsCaptureTimeExtension from time.Time and a clock offset.
func (
	 time.Time,
	 time.Duration,
) *AbsCaptureTimeExtension {
	 := .Nanoseconds()
	 := false
	if  < 0 {
		 = -
		 = true
	}
	 := ( / 1e9) & 0xFFFFFFFF
	 := ((( % 1e9) * (1 << 32)) / 1e9) & 0xFFFFFFFF
	 := ( << 32) | 
	if  {
		 = -
	}

	return &AbsCaptureTimeExtension{
		Timestamp:                   toNtpTime(),
		EstimatedCaptureClockOffset: &,
	}
}