package main

import (
	"fmt"
	"log"
	"net/http"
	"sync"
	"time"

	"github.com/gin-gonic/gin"
)

type Message struct {
	Data interface{} `json:"data"`
	Id   string      `json:"id"`
}

type Client struct {
	Channel chan Message `json:"clients"`
}

var (
	clients      = make(map[*Client]bool)
	clientsMutex sync.Mutex
	broadcast    = make(chan Message)
)

func SSEHandler(c *gin.Context) {
	client := &Client{
		Channel: make(chan Message),
	}

	log.Printf("events: %+v", client)

	AddClient(client)

	defer unregisterClient(client)

	log.Printf("Client %s connected", client)

	c.Writer.Header().Set("Content-Type", "text/event-stream")
	c.Writer.Header().Set("Cache-Control", "no-cache")
	c.Writer.Header().Set("Connection", "keep-alive")
	c.Writer.Header().Set("Transfer-Encoding", "chunked")

	for {
		select {
		case msg := <-client.Channel:
			fmt.Fprintf(c.Writer, "data: %s\n\n", msg.Data)
			c.Writer.Flush()
		case <-c.Writer.CloseNotify():
			return
		}
	}
}

func AddClient(client *Client) {
	clientsMutex.Lock()
	clients[client] = true
	clientsMutex.Unlock()
}

func unregisterClient(client *Client) {
	clientsMutex.Lock()
	delete(clients, client)
	close(client.Channel)
	clientsMutex.Unlock()
}

func SendMsg(c *gin.Context) {
	var msg Message
	c.ShouldBind(&msg)
	msg.Id = time.Now().Format(time.RFC3339)
	broadcast <- msg
	c.JSON(http.StatusOK, gin.H{"status": "sent"})
}

func handleMessages() {
	for {
		msg := <-broadcast
		clientsMutex.Lock()
		for client := range clients {
			client.Channel <- msg
		}
		clientsMutex.Unlock()
	}
}
