package room

import (
	"encoding/json"
	"testing"
)

// Broadcast cost decides whether a crowd can watch the same round. At 60Hz
// with N subscribers the server does N marshals per tick unless the payload is
// serialised once and shared.
func BenchmarkSnapshotMarshal(b *testing.B) {
	r := New("rocket", nil, nil)
	for i := 0; i < 200; i++ {
		r.bets[int64(i)] = &Bet{
			AccountID: int64(i),
			Pubkey:    []byte("0123456789abcdef0123456789abcdef"),
			Nickname:  "player",
			StakeMsat: 10000,
		}
	}
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		snap := r.Snapshot()
		if _, err := json.Marshal(snap); err != nil {
			b.Fatal(err)
		}
	}
}

// Snapshot alone, without serialisation: this is the lock-held portion, which
// blocks every other operation on the room.
func BenchmarkSnapshotOnly(b *testing.B) {
	r := New("rocket", nil, nil)
	for i := 0; i < 200; i++ {
		r.bets[int64(i)] = &Bet{
			AccountID: int64(i),
			Pubkey:    []byte("0123456789abcdef0123456789abcdef"),
			Nickname:  "player",
			StakeMsat: 10000,
		}
	}
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		_ = r.Snapshot()
	}
}

// Fan-out to many subscriber channels.
func BenchmarkBroadcast1000Subscribers(b *testing.B) {
	r := New("rocket", nil, nil)
	for i := 0; i < 50; i++ {
		r.bets[int64(i)] = &Bet{
			AccountID: int64(i), Pubkey: []byte("key"),
			Nickname: "p", StakeMsat: 1000,
		}
	}
	// Drain subscribers so the buffered channels do not simply fill.
	for i := 0; i < 1000; i++ {
		ch, _ := r.Subscribe()
		go func(c <-chan []byte) {
			for range c {
			}
		}(ch)
	}
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		r.broadcast()
	}
}
