package util

// DTSEstimator is a DTS estimator.
type DTSEstimator struct {
	hasB     bool
	prevPTS  uint32
	prevDTS  uint32
	cache    []uint32
	interval uint32
}

func (d *DTSEstimator) Clone() *DTSEstimator {
	return &DTSEstimator{
		d.hasB,
		d.prevPTS,
		d.prevDTS,
		append([]uint32(nil), d.cache...),
		d.interval,
	}
}

func (d *DTSEstimator) add(pts uint32) {
	i := 0
	l := len(d.cache)
	if l >= 4 {
		l--
		// i = l - 3
		d.cache = append(d.cache[:0], d.cache[1:]...)[:l]
	}

	for ; i < l; i = i + 1 {
		if d.cache[i] > pts {
			break
		}
	}
	d.cache = append(d.cache, pts)
	d.cache = append(d.cache[:i+1], d.cache[i:l]...)
	d.cache[i] = pts
}

// Feed provides PTS to the estimator, and returns the estimated DTS.
func (d *DTSEstimator) Feed(pts uint32) uint32 {
	interval := Conditional(pts > d.prevPTS, pts-d.prevPTS, d.prevPTS-pts)
	if interval > 10*d.interval {
		*d = DTSEstimator{}
	}
	d.interval = interval
	d.add(pts)
	dts := pts
	if !d.hasB {
		if pts < d.prevPTS {
			d.hasB = true
			dts = d.cache[0]
		}
	} else {
		dts = d.cache[0]
	}

	if d.prevDTS > dts {
		dts = d.prevDTS
	}
	// if d.prevDTS >= dts {
	// 	dts = d.prevDTS + 90
	// }
	d.prevPTS = pts
	d.prevDTS = dts
	return dts
}
