package aoiprxkit

type jitterBuffer struct {
	started  bool
	expected uint16
	maxDepth int
	packets  map[uint16]RTPPacket
}

func newJitterBuffer(maxDepth int) *jitterBuffer {
	return &jitterBuffer{maxDepth: maxDepth, packets: make(map[uint16]RTPPacket)}
}

func (j *jitterBuffer) push(pkt RTPPacket) (ready []RTPPacket, lateDrop bool, gapLoss uint64, reorder bool) {
	if !j.started {
		j.started = true
		j.expected = pkt.SequenceNumber
	}
	if seqDistance(pkt.SequenceNumber, j.expected) < 0 {
		return nil, true, 0, false
	}
	if _, exists := j.packets[pkt.SequenceNumber]; !exists {
		j.packets[pkt.SequenceNumber] = pkt
		if pkt.SequenceNumber != j.expected {
			reorder = true
		}
	}
	for {
		pkt, ok := j.packets[j.expected]
		if !ok {
			break
		}
		ready = append(ready, pkt)
		delete(j.packets, j.expected)
		j.expected++
	}
	for len(j.packets) > j.maxDepth {
		if _, ok := j.packets[j.expected]; ok {
			break
		}
		j.expected++
		gapLoss++
		for {
			pkt, ok := j.packets[j.expected]
			if !ok {
				break
			}
			ready = append(ready, pkt)
			delete(j.packets, j.expected)
			j.expected++
		}
	}
	return ready, false, gapLoss, reorder
}

func seqDistance(a, b uint16) int {
	return int(int16(a - b))
}
