package esr

import (
	"fmt"
	"net/http"
	"time"
)

type LiveReload struct {
	clients  map[chan string]bool
	incoming chan chan string
	outgoing chan chan string
	messages chan string
}

func NewLiveReload() *LiveReload {
	return &LiveReload{
		clients:  make(map[chan string]bool),
		incoming: make(chan chan string),
		outgoing: make(chan chan string),
		messages: make(chan string),
	}
}

func (l *LiveReload) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	flusher, ok := w.(http.Flusher)
	if !ok {
		http.Error(w, "Streaming unsupported!", http.StatusInternalServerError)
		return
	}

	clientChan := make(chan string)
	l.incoming <- clientChan
	defer func() { l.outgoing <- clientChan }()

	w.Header().Set("Content-Type", "text/event-stream")
	w.Header().Set("Cache-Control", "no-cache")
	w.Header().Set("Connection", "keep-alive")
	w.WriteHeader(http.StatusOK)

	for {
		select {
		case message, ok := <-clientChan:
			if !ok {
				return
			}
			_, _ = fmt.Fprintf(w, "data: %s\n\n", message)
			flusher.Flush()
		case <-r.Context().Done():
			return
		}
	}
}

func (l *LiveReload) Start() {
	go func() {
		for {
			select {
			case client := <-l.incoming:
				l.clients[client] = true
			case client := <-l.outgoing:
				delete(l.clients, client)
				close(client)
			case msg := <-l.messages:
				for client := range l.clients {
					client <- msg
				}
			}
		}
	}()

	go func() {
		for range time.Tick(time.Minute) {
			l.messages <- "waiting"
		}
	}()
}

func (l *LiveReload) Reload() {
	l.messages <- "reload"
}
