package api

import (
	"sync"
	"time"
)

type MessageQueue struct {
	items          []Message
	itemMutex      *sync.Mutex
	listeners      map[int64]chan Message
	listenersMutex *sync.Mutex
}

func (mq *MessageQueue) Broadcast(msg string) {
	mq.itemMutex.Lock()
	m := Message{
		Timestamp: time.Now().UnixNano(),
		Content:   msg,
	}
	mq.items = append(mq.items, m)
	for _, l := range mq.listeners {
		l <- m
	}
	mq.itemMutex.Unlock()
}

func (mq *MessageQueue) Poll(since int64) []Message {
	startIndex := 0
	for i, m := range mq.items {
		if m.Timestamp > since {
			startIndex = i
			break
		}
	}
	return mq.items[startIndex:]
}

func (mq *MessageQueue) Listen(since int64) (int64, <-chan Message) {
	ch := make(chan Message)
	mq.itemMutex.Lock()
	msgs := mq.Poll(since)
	for _, msg := range msgs {
		ch <- msg
	}
	mq.listenersMutex.Lock()
	id := time.Now().UnixNano()
	mq.listeners[id] = ch
	mq.listenersMutex.Unlock()
	mq.itemMutex.Unlock()
	return id, ch
}

func (mq *MessageQueue) Unlisten(id int64) {
	delete(mq.listeners, id)
}

type Message struct {
	Timestamp int64
	Content   string
}
