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

package rtp

import (
	
)

const (
	absSendTimeExtensionSize = 3
)

// AbsSendTimeExtension is a extension payload format in
// http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
type AbsSendTimeExtension struct {
	Timestamp uint64
}

// Marshal serializes the members to buffer.
func ( AbsSendTimeExtension) () ([]byte, error) {
	return []byte{
		byte(.Timestamp & 0xFF0000 >> 16),
		byte(.Timestamp & 0xFF00 >> 8),
		byte(.Timestamp & 0xFF),
	}, nil
}

// Unmarshal parses the passed byte slice and stores the result in the members.
func ( *AbsSendTimeExtension) ( []byte) error {
	if len() < absSendTimeExtensionSize {
		return errTooSmall
	}
	.Timestamp = uint64([0])<<16 | uint64([1])<<8 | uint64([2])

	return nil
}

// Estimate absolute send time according to the receive time.
// Note that if the transmission delay is larger than 64 seconds, estimated time will be wrong.
func ( *AbsSendTimeExtension) ( time.Time) time.Time {
	 := toNtpTime()
	 := &0xFFFFFFC000000000 | (.Timestamp&0xFFFFFF)<<14
	if  <  {
		// Receive time must be always later than send time
		 -= 0x1000000 << 14
	}

	return toTime()
}

// NewAbsSendTimeExtension makes new AbsSendTimeExtension from time.Time.
func ( time.Time) *AbsSendTimeExtension {
	return &AbsSendTimeExtension{
		Timestamp: toNtpTime() >> 14,
	}
}

func toNtpTime( time.Time) uint64 {
	var  uint64
	var  uint64
	 := uint64(.UnixNano()) // nolint: gosec // G115 false positive
	 =  / 1e9
	 += 0x83AA7E80 // offset in seconds between unix epoch and ntp epoch
	 =  % 1e9
	 <<= 32
	 /= 1e9
	 <<= 32

	return  | 
}

func toTime( uint64) time.Time {
	 :=  >> 32
	 :=  & 0xFFFFFFFF
	 *= 1e9
	 >>= 32
	 -= 0x83AA7E80
	 := *1e9 + 

	return time.Unix(0, int64()) // nolint: gosec // G115 false positive
}