package clients

import (
	"fmt"

	"git.elnu.com/ElnuDev/jichanorg/httputils"
)

type Client = chan []httputils.SseEvent

const EventWord = "word"
const EventPlayerCount = "players"
const EventNavigate = "navigate"

type ClientSet struct {
	clients map[Client]bool
}

func NewClientSet() ClientSet {
	return ClientSet{make(map[Client]bool)}
}

func (clients ClientSet) Broadcast(events ...httputils.SseEvent) {
	for client := range clients.clients {
		client <- events
	}
}

func (clients ClientSet) PlayerCount() int {
	return len(clients.clients)
}

func (clients ClientSet) PlayerCountEvent(offset int) httputils.SseEvent {
	playerCount := clients.PlayerCount() + offset
	var data string
	if playerCount == 0 {
		data = "No players online."
	} else {
		data = fmt.Sprintf("%d player%s online.", playerCount, map[bool]string{true: "", false: "s"}[playerCount == 1])
	}
	return httputils.SseEvent{EventName: EventPlayerCount, Data: data}
}

func (clients ClientSet) BroadcastPlayerCount(offset int) {
	clients.Broadcast(clients.PlayerCountEvent(offset))
}

func (clients ClientSet) BroadcastWord(word string) {
	clients.Broadcast(
		httputils.SseEvent{
			EventName: EventWord,
			Data:      fmt.Sprintf("<div>%s</div>", word),
		},
		httputils.SseEvent{
			EventName: EventNavigate,
			Data:      fmt.Sprintf("https://jisho.org/search/%s", word),
		},
	)
}

func (clients ClientSet) Connect(client Client) {
	// Channels are blocking.
	// Client initialization is waiting for connect() to complete.
	// If we try to braodcast to it before connect() is done,
	// the channel handling logic wouldn't have started yet,
	// and broadcast() would be freeze.
	// Therefore, we must broadcast an offset player count first,
	// then actually add the client.
	clients.BroadcastPlayerCount(1)
	clients.clients[client] = true
}

func (clients ClientSet) Disconnect(client Client) {
	delete(clients.clients, client)
	clients.BroadcastPlayerCount(0)
}