// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file
package catapult_test

import (
	"math"
	"reflect"
	"testing"

	"fuchsia.googlesource.com/infra/infra/catapult"
)

// Expects NewLinearBoundaries to return an error when called with the given
// arguments.
func expectCreationFailure(t *testing.T, centralBinCount uint, min float64, max float64) {
	if _, err := catapult.NewLinearBinBoundaries(centralBinCount, min, max); err == nil {
		t.Errorf("expected an error, given (centralBinCount,min,max)=(%v,%v,%v). "+
			"Error was nil.", centralBinCount, min, max)
	}
}

// Expects GetBinIndex to return the given index for the given value.
func expectBinIndex(t *testing.T, bb *catapult.BinBoundaries, index uint, value float64) {
	if actualBin := bb.GetBinIndex(value); actualBin != index {
		t.Errorf("expected bin %v for %v with boundaries: %v Got bin %v",
			index, value, bb.GetBoundaries(), actualBin)
	}
}

// Expects BinBoundaries created from the given centralBinCount, min, and max to have
// the given boundaries.
func expectBoundaries(t *testing.T, centralBinCount uint, min float64, max float64, boundaries []float64) {
	bb, err := catapult.NewLinearBinBoundaries(centralBinCount, min, max)
	if err != nil {
		t.Errorf("failed to create BinBoundaries %v", err)
	}

	actualBoundaries := bb.GetBoundaries()
	if !reflect.DeepEqual(actualBoundaries, boundaries) {
		t.Errorf("expected boundaries %v. Got %v", boundaries, actualBoundaries)
	}
}

func TestNewLinearBinBoundaries(t *testing.T) {
	t.Run("should err when given centralBinCount < 1", func(t *testing.T) {
		expectCreationFailure(t, 0, math.Inf(1), math.Inf(-1))
	})

	t.Run("should err when min >= max", func(t *testing.T) {
		centralBinCount := uint(10)
		expectCreationFailure(t, centralBinCount, 4, 4)
		expectCreationFailure(t, centralBinCount, 5, 4)
	})

	t.Run("should return BinBoundaries", func(t *testing.T) {
		bb, err := catapult.NewLinearBinBoundaries(10, 20, 30)
		if err != nil || bb == nil {
			t.Errorf("expected BinBoundaries. Got %v and error: %v",
				bb, err)
		}
	})
}

func TestBinBoundaries_GetBin_Linear(t *testing.T) {
	t.Run("centralBinCount=1", func(t *testing.T) {
		// We're using 1 central bin with a min and max of 0 and 10.  Our bins
		// should consist of an underflow bin, a central bin and an overflow bin
		// with the following shape:
		//
		//              0         10
		//              |         |
		//              |         |
		// -Inf <-------|---------|--------> Inf
		//  : underflow : central : overflow :
		//  :    bin    :   bin   :   bin    :
		bb, err := catapult.NewLinearBinBoundaries(1, 0, 10)
		if err != nil {
			t.Errorf("failed to create BinBoundaries %v", err)
		}

		// Constant bin indices for our boundaries.
		const underflow, central, overflow uint = 0, 1, 2

		// Values <0 belong in underflow bin
		t.Run("underflow bin", func(t *testing.T) {
			expectBinIndex(t, bb, underflow, -100)
			expectBinIndex(t, bb, underflow, -1)
			expectBinIndex(t, bb, underflow, -1e-10)
		})
		// Values >=0 and <10 belong in central bin
		t.Run("central bin", func(t *testing.T) {
			expectBinIndex(t, bb, central, 0)
			expectBinIndex(t, bb, central, 7)
			expectBinIndex(t, bb, central, 9.9999)
		})
		// Values >=10 belong in overflow bin
		t.Run("overflow bin", func(t *testing.T) {
			expectBinIndex(t, bb, overflow, 10)
			expectBinIndex(t, bb, overflow, 10.000000001)
			expectBinIndex(t, bb, overflow, 100)
		})
	})

	t.Run("centralBinCount>1", func(t *testing.T) {
		// We're using 2 central bins with a min and max of 7 and 14.  Our bins
		// should consist of an underflow bin, a central bin and an overflow bin
		// bin with the following shape:
		//
		//              7       10.5      14
		//              |         |        |
		//              |         |        |
		// -Inf <-------|---------|--------|--------> Inf
		//  : underflow : central :central : overflow :
		//  :    bin    :  bin0   :  bin1  :  bin     :
		bb, err := catapult.NewLinearBinBoundaries(2, 7, 14)
		if err != nil {
			t.Errorf("failed to create BinBoundaries %v", err)
		}

		// Constant bin indices for our boundaries.
		const underflow, central0, central1, overflow uint = 0, 1, 2, 3

		// Values <7 belong in underflow bin
		t.Run("underflow bin", func(t *testing.T) {
			expectBinIndex(t, bb, underflow, -99999)
			expectBinIndex(t, bb, underflow, 0)
			expectBinIndex(t, bb, underflow, 4)
			expectBinIndex(t, bb, underflow, 6.999999999)
		})
		// Values >=7 and <10.5 belong in first central bin
		t.Run("first central bin", func(t *testing.T) {
			expectBinIndex(t, bb, central0, 7)
			expectBinIndex(t, bb, central0, 7.0000000001)
			expectBinIndex(t, bb, central0, 9)
			expectBinIndex(t, bb, central0, 10.499999999999)
		})
		// Values >=10.5 and < 14 belong in second central bin
		t.Run("second central bin", func(t *testing.T) {
			expectBinIndex(t, bb, central1, 10.5)
			expectBinIndex(t, bb, central1, 10.500000000001)
			expectBinIndex(t, bb, central1, 12)
			expectBinIndex(t, bb, central1, 13.99999999999)
		})
		// Values >=14 belong in overflow bin
		t.Run("third central bin", func(t *testing.T) {
			expectBinIndex(t, bb, overflow, 14)
			expectBinIndex(t, bb, overflow, 14.000000001)
			expectBinIndex(t, bb, overflow, 10000)
		})
	})
}

func TestBinBoundaries_GetBoundaries(t *testing.T) {
	t.Run("centralBinCount==1", func(t *testing.T) {
		expectBoundaries(t, 1, -3, 3, []float64{-3, 3})
		expectBoundaries(t, 1, 1e-5, 1e-4, []float64{1e-5, 1e-4})
	})
	t.Run("centralBinCount>1", func(t *testing.T) {
		expectBoundaries(t, 2, -100, 10, []float64{-100, -45, 10})
		expectBoundaries(t, 3, 0, 20, []float64{0, 20.0 / 3, 40.0 / 3, 20})
	})
}

func TestBinBoundaries_BinCount(t *testing.T) {
	centralBinCount := uint(123)
	bb, err := catapult.NewLinearBinBoundaries(centralBinCount, 0, 1)
	if err != nil {
		t.Errorf("failed to create BinBoundaries %v", err)
	}

	actualCount := bb.BinCount()
	if actualCount != centralBinCount+2 {
		t.Errorf("expect bin count %v. Got %v", centralBinCount, actualCount)
	}
}
