package pubsubclient

import (
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

func TestSubscriptions(t *testing.T) {
	assert := assert.New(t)

	sub := &subscriptions{
		subsByToken: map[string]stringSet{
			"at1": stringSet{
				"t1": struct{}{},
				"t2": struct{}{},
			},
		},
	}

	sub.listen(&listenMsg{
		Data: topicList{
			Topics:    []string{"t3"},
			AuthToken: "at1",
		},
	})

	have := sub.replay()

	require.Len(t, have, 1)
	assert.Len(have[0].Data.Topics, 3)
	assert.Contains(have[0].Data.Topics, "t1")
	assert.Contains(have[0].Data.Topics, "t2")
	assert.Contains(have[0].Data.Topics, "t3")
	assert.Equal("at1", have[0].Data.AuthToken)

	sub.unlisten(&unlistenMsg{
		Data: topicList{
			Topics: []string{"t2"},
		},
	})

	have = sub.replay()

	require.Len(t, have, 1)
	assert.Len(have[0].Data.Topics, 2)
	assert.Contains(have[0].Data.Topics, "t1")
	assert.Contains(have[0].Data.Topics, "t3")
	assert.Equal("at1", have[0].Data.AuthToken)

}

func TestSubscriptionListenMultipleTokens(t *testing.T) {
	assert := assert.New(t)

	sub := &subscriptions{
		subsByToken: map[string]stringSet{
			"at1": stringSet{
				"t1": struct{}{},
				"t2": struct{}{},
			},
			"at2": stringSet{
				"t3": struct{}{},
			},
		},
	}

	sub.listen(&listenMsg{
		Data: topicList{
			Topics:    []string{"t3"},
			AuthToken: "at1",
		},
	})

	have := sub.replay()

	require.Len(t, have, 2)
	if have[0].Data.AuthToken == "at1" {
		assert.Len(have[0].Data.Topics, 3)
		assert.Contains(have[0].Data.Topics, "t1")
		assert.Contains(have[0].Data.Topics, "t2")
		assert.Contains(have[0].Data.Topics, "t3")

		assert.Len(have[1].Data.Topics, 1)
		assert.Contains(have[1].Data.Topics, "t3")
	} else {
		assert.Len(have[1].Data.Topics, 3)
		assert.Contains(have[1].Data.Topics, "t1")
		assert.Contains(have[1].Data.Topics, "t2")
		assert.Contains(have[1].Data.Topics, "t3")

		assert.Len(have[0].Data.Topics, 1)
		assert.Contains(have[0].Data.Topics, "t3")
	}

	sub.unlisten(&unlistenMsg{
		Data: topicList{
			Topics: []string{"t3"},
		},
	})

	have = sub.replay()

	require.Len(t, have, 1)
	assert.Len(have[0].Data.Topics, 2)
	assert.Contains(have[0].Data.Topics, "t1")
	assert.Contains(have[0].Data.Topics, "t2")
}
