package runtimeconfig

import (
	"encoding/json"
	"testing"
	"time"
)

func TestStoreSetDeleteAndSubscribe(t *testing.T) {
	store := NewStore()
	updates := make(chan Config, 2)
	stop := store.Subscribe("mq", "rabbitmq", func(config Config) { updates <- config })
	defer stop()

	store.Set(Config{Kind: "MQ", Provider: "RabbitMQ", Enabled: true, Values: json.RawMessage(`{"host":"localhost"}`)})
	loaded, ok := store.Get("mq", "rabbitmq")
	if !ok || !loaded.Enabled || string(loaded.Values) != `{"host":"localhost"}` {
		t.Fatalf("loaded config = %#v, ok=%v", loaded, ok)
	}
	if update := <-updates; !update.Enabled {
		t.Fatalf("set update = %#v", update)
	}

	store.Delete("mq", "rabbitmq")
	if _, ok = store.Get("mq", "rabbitmq"); ok {
		t.Fatal("deleted config remained in store")
	}
	if update := <-updates; update.Enabled {
		t.Fatalf("delete update = %#v", update)
	}
}

func TestStoreReplaceSkipsUnchangedValues(t *testing.T) {
	store := NewStore()
	updates := make(chan Config, 2)
	stop := store.Subscribe("mq", "rabbitmq", func(config Config) { updates <- config })
	defer stop()

	config := Config{Kind: "mq", Provider: "rabbitmq", Enabled: true, Values: json.RawMessage(`{"host":"localhost"}`)}
	store.Set(config)
	select {
	case <-updates:
	case <-time.After(time.Second):
		t.Fatal("initial set notification was not delivered")
	}

	store.Replace([]Config{config})
	select {
	case update := <-updates:
		t.Fatalf("unchanged replace emitted notification: %#v", update)
	case <-time.After(20 * time.Millisecond):
	}

	changed := config
	changed.Values = json.RawMessage(`{"host":"other"}`)
	store.Replace([]Config{changed})
	select {
	case update := <-updates:
		if string(update.Values) != string(changed.Values) {
			t.Fatalf("changed replace = %#v", update)
		}
	case <-time.After(time.Second):
		t.Fatal("changed replace notification was not delivered")
	}
}

func TestStoreSetSkipsUnchangedValues(t *testing.T) {
	var store Store
	updates := make(chan Config, 1)
	stop := store.Subscribe("mq", "rabbitmq", func(config Config) { updates <- config })
	defer stop()
	config := Config{Kind: "mq", Provider: "rabbitmq", Enabled: true, Values: json.RawMessage(`{"host":"localhost"}`)}
	store.Set(config)
	select {
	case <-updates:
	case <-time.After(time.Second):
		t.Fatal("initial set notification was not delivered")
	}
	store.Set(config)
	select {
	case update := <-updates:
		t.Fatalf("unchanged set emitted notification: %#v", update)
	case <-time.After(20 * time.Millisecond):
	}
}
