package ioprogress

import (
	"time"
)

// ProgressTracker provides the stream information needed for tracking.
type ProgressTracker struct {
	Length  int64
	Handler func(int64, int64)

	percentage float64
	total      int64
	start      *time.Time
	last       *time.Time
}

func (pt *ProgressTracker) update(n int) {
	// Skip the rest if no handler attached
	if pt.Handler == nil {
		return
	}

	// Initialize start time if needed
	if pt.start == nil {
		cur := time.Now()
		pt.start = &cur
		pt.last = pt.start
	}

	// Skip if no data to count
	if n <= 0 {
		return
	}

	// Update interval handling
	var percentage float64
	if pt.Length > 0 {
		// If running in relative mode, check that we increased by at least 1%
		percentage = float64(pt.total) / float64(pt.Length) * float64(100)
		if percentage-pt.percentage < 0.9 {
			return
		}
	} else {
		// If running in absolute mode, check that at least a second elapsed
		interval := time.Since(*pt.last).Seconds()
		if interval < 1 {
			return
		}
	}

	// Determine speed
	speedInt := int64(0)
	duration := time.Since(*pt.start).Seconds()
	if duration > 0 {
		speed := float64(pt.total) / duration
		speedInt = int64(speed)
	}

	// Determine progress
	var progressInt int64
	if pt.Length > 0 {
		pt.percentage = percentage
		progressInt = min(int64(1+int(percentage)), 100)

		// Cap maximum download speed to file size.
		if speedInt > pt.Length {
			speedInt = pt.Length
		}
	} else {
		progressInt = pt.total

		// Update timestamp
		cur := time.Now()
		pt.last = &cur
	}

	pt.Handler(progressInt, speedInt)
}
