package main

import (
	"math"
	"testing"
	"time"
)

func TestMomentaryOutput(t *testing.T) {
	mo := momentaryOutput{}
	mo.trigger()
	mo.process()
	if !mo.output {
		t.Fatalf("output didn't trigger")
	}
	mo.process()
	if !mo.output {
		t.Fatalf("output didn't keep triggered")
	}
	time.Sleep(time.Second)
	mo.process()
	if mo.output {
		t.Fatalf("output didn't untrigger")
	}
}

func TestThresholdOutput(t *testing.T) {
	to := thresholdOutput{
		threshold:  1,
		hysteresis: 0.2,
	}
	to.process(0.7)
	if to.output {
		t.Fatalf("output shouldn't have triggered")
	}
	to.process(1)
	if to.output {
		t.Fatalf("output shouldn't have triggered")
	}
	to.process(1.3)
	if !to.output {
		t.Fatalf("output should have triggered")
	}
	to.process(1)
	if !to.output {
		t.Fatalf("output should have triggered")
	}
	to.process(0.7)
	if !to.output {
		t.Fatalf("output should have triggered (in debounce)")
	}

	// let debounce timeout pass
	time.Sleep(time.Second * 6)

	to.process(0.7)
	if to.output {
		t.Fatalf("output shouldn't have triggered")
	}
}

func TestRingbufferInput(t *testing.T) {
	ri := ringbufferInput{
		limit: 3,
	}
	if ri.saturated() {
		t.Fatal("ringbuffer shouldn't be saturated yet")
	}
	ri.process(1)
	if ri.saturated() {
		t.Fatal("ringbuffer shouldn't be saturated yet")
	}
	ri.process(2)
	if ri.saturated() {
		t.Fatal("ringbuffer shouldn't be saturated yet")
	}
	ri.process(3)
	if !ri.saturated() {
		t.Fatalf("ringbuffer should be saturated")
	}

	if diff := math.Abs(float64(ri.avg) - 2); diff > 0.01 {
		t.Fatalf("ringbuffer avg should be ~2, is %f", ri.avg)
	}
	ri.process(10)
	if diff := math.Abs(float64(ri.avg) - 5); diff > 0.01 {
		t.Fatalf("ringbuffer avg should be ~5, is %f", ri.avg)
	}
}