package main

import (
	"context"
	"crypto/sha256"
	"encoding/binary"
	"errors"
	"fmt"
	"golang.org/x/sync/singleflight"
	"math"
	"sync/atomic"
)

type Bloom uint64

func positions(s string) (uint64, uint64) {
	h := sha256.Sum256([]byte(s))
	return binary.LittleEndian.Uint64(h[:8]) % 64, binary.LittleEndian.Uint64(h[8:16]) % 64
}
func (b *Bloom) Add(s string) { a, c := positions(s); *b |= Bloom(1<<a | 1<<c) }
func (b Bloom) Maybe(s string) bool {
	a, c := positions(s)
	return b&Bloom(1<<a) != 0 && b&Bloom(1<<c) != 0
}
func bloomDemo() (bool, string) {
	var b Bloom
	for i := 0; i < 12; i++ {
		b.Add(fmt.Sprint("member-", i))
	}
	all := true
	for i := 0; i < 12; i++ {
		all = all && b.Maybe(fmt.Sprint("member-", i))
	}
	for i := 0; i < 100000; i++ {
		s := fmt.Sprint("absent-", i)
		if b.Maybe(s) {
			return all, s
		}
	}
	panic("fixed fixture produced no false positive")
}
func mergedWave() (int64, int, int64) {
	var g singleflight.Group
	var calls atomic.Int64
	gate := make(chan struct{})
	results := make([]<-chan singleflight.Result, 20)
	for i := range results {
		results[i] = g.DoChan("tenant:7:item:9", func() (any, error) { calls.Add(1); <-gate; return "value", nil })
	}
	close(gate)
	shared := 0
	for _, ch := range results {
		r := <-ch
		if r.Err != nil || r.Val != "value" {
			panic("bad result")
		}
		if r.Shared {
			shared++
		}
	}
	first := calls.Load()
	g.Do("tenant:7:item:9", func() (any, error) { calls.Add(1); return "again", nil })
	return first, shared, calls.Load()
}
func await(ctx context.Context, ch <-chan singleflight.Result) (any, error) {
	select {
	case <-ctx.Done():
		return nil, ctx.Err()
	case r := <-ch:
		return r.Val, r.Err
	}
}
func cancelledWaiter() (bool, string) {
	var g singleflight.Group
	gate := make(chan struct{})
	leader := g.DoChan("k", func() (any, error) { <-gate; return "completed", nil })
	follower := g.DoChan("k", func() (any, error) { panic("must be merged") })
	ctx, cancel := context.WithCancel(context.Background())
	cancel()
	_, err := await(ctx, follower) // No result can arrive until gate is opened.
	close(gate)
	r := <-leader
	return errors.Is(err, context.Canceled), r.Val.(string)
}
func main() {
	all, fp := bloomDemo()
	fmt.Printf("bloom: inserted-all-present=%v false-positive=%s\n", all, fp)
	n, p := 1000000.0, 0.01
	m := math.Ceil(-n * math.Log(p) / (math.Ln2 * math.Ln2))
	k := math.Round(m / n * math.Ln2)
	fmt.Printf("design: bits=%.0f MiB=%.3f hashes=%.0f\n", m, m/8/(1<<20), k)
	first, shared, second := mergedWave()
	fmt.Printf("singleflight: requests=20 backend=%d shared=%d after-next=%d\n", first, shared, second)
	canceled, value := cancelledWaiter()
	fmt.Printf("waiter: canceled=%v leader=%s\n", canceled, value)
}
