package main

import (
	"testing"
	"time"

	rtest "github.com/restic/restic/internal/test"
	"github.com/restic/restic/internal/ui"
)

func TestSizeHistogramNew(t *testing.T) {
	h := newSizeHistogram(42)

	exp := &sizeHistogram{
		count:     0,
		totalSize: 0,
		buckets: []sizeClass{
			{0, 0, 0},
			{1, 9, 0},
			{10, 42, 0},
		},
	}

	rtest.Equals(t, exp, h)
}

func TestSizeHistogramAdd(t *testing.T) {
	h := newSizeHistogram(42)
	for i := uint64(0); i < 45; i++ {
		h.Add(i)
	}

	exp := &sizeHistogram{
		count:     45,
		totalSize: 990,
		buckets: []sizeClass{
			{0, 0, 1},
			{1, 9, 9},
			{10, 42, 33},
		},
		oversized: []uint64{43, 44},
	}

	rtest.Equals(t, exp, h)
}

func TestSizeHistogramString(t *testing.T) {
	t.Run("overflow", func(t *testing.T) {
		h := newSizeHistogram(42)
		h.Add(8)
		h.Add(50)

		rtest.Equals(t, "Count: 2\nTotal Size: 58 B\nSize        Count\n-----------------\n1 - 9 Byte  1\n-----------------\nOversized: [50]\n", h.String())
	})

	t.Run("withZero", func(t *testing.T) {
		h := newSizeHistogram(42)
		h.Add(0)
		h.Add(1)
		h.Add(10)

		rtest.Equals(t, "Count: 3\nTotal Size: 11 B\nSize          Count\n-------------------\n  0 - 0 Byte  1\n  1 - 9 Byte  1\n10 - 42 Byte  1\n-------------------\n", h.String())
	})
}

func TestStatsProgress(t *testing.T) {
	term := &ui.MockTerminal{}

	progress := newStatsProgress(term, true, 2)
	progress.printProgress(0*time.Second, false)
	rtest.Equals(t, []string{"[0:00] 0.00%  0 / 2 snapshots, 0 B"}, term.Output)

	progress.processSnapshot()
	progress.update(1, 2, 3)
	progress.printProgress(5*time.Second, false)
	// Output differs from the previous one because the progress is based on the number of processed snapshots,
	// 1/2 snapshots means processing the snapshot 1 currently
	rtest.Equals(t, []string{"[0:05] 0.00%  1 / 2 snapshots, 1 files, 2 blobs, 3 B"}, term.Output)

	progress.processSnapshot()
	progress.printProgress(10*time.Second, false)
	rtest.Equals(t, []string{"[0:10] 50.00%  2 / 2 snapshots, 0 B"}, term.Output)

	progress.update(4, 5, 6)
	progress.printProgress(15*time.Second, false)
	rtest.Equals(t, []string{"[0:15] 50.00%  2 / 2 snapshots, 4 files, 5 blobs, 6 B"}, term.Output)

	progress.printProgress(20*time.Second, true)
	rtest.Equals(t, []string{"[0:20] 100.00%  2 / 2 snapshots, 4 files, 5 blobs, 6 B"}, term.Output)
}

func TestStatsProgressJSON(t *testing.T) {
	term := &ui.MockTerminal{}

	progress := newStatsProgress(term, false, 2)
	progress.printProgress(0*time.Second, false)
	// JSON output is not available yet, so just make sure to not break normal json output
	rtest.Equals(t, nil, term.Output)
}
