package pubsub

import (
	

	
)

// NewMessageCache creates a sliding window cache that remembers messages for as
// long as `history` slots.
//
// When queried for messages to advertise, the cache only returns messages in
// the last `gossip` slots.
//
// The `gossip` parameter must be smaller or equal to `history`, or this
// function will panic.
//
// The slack between `gossip` and `history` accounts for the reaction time
// between when a message is advertised via IHAVE gossip, and the peer pulls it
// via an IWANT command.
func (,  int) *MessageCache {
	if  >  {
		 := fmt.Errorf("invalid parameters for message cache; gossip slots (%d) cannot be larger than history slots (%d)",
			, )
		panic()
	}
	return &MessageCache{
		msgs:    make(map[string]*Message),
		peertx:  make(map[string]map[peer.ID]int),
		history: make([][]CacheEntry, ),
		gossip:  ,
		msgID: func( *Message) string {
			return DefaultMsgIdFn(.Message)
		},
	}
}

type MessageCache struct {
	msgs    map[string]*Message
	peertx  map[string]map[peer.ID]int
	history [][]CacheEntry
	gossip  int
	msgID   func(*Message) string
}

func ( *MessageCache) ( func(*Message) string) {
	.msgID = 
}

type CacheEntry struct {
	mid   string
	topic string
}

func ( *MessageCache) ( *Message) {
	 := .msgID()
	.msgs[] = 
	.history[0] = append(.history[0], CacheEntry{mid: , topic: .GetTopic()})
}

func ( *MessageCache) ( string) (*Message, bool) {
	,  := .msgs[]
	return , 
}

func ( *MessageCache) ( string,  peer.ID) (*Message, int, bool) {
	,  := .msgs[]
	if ! {
		return nil, 0, false
	}

	,  := .peertx[]
	if ! {
		 = make(map[peer.ID]int)
		.peertx[] = 
	}
	[]++

	return , [], true
}

func ( *MessageCache) ( string) []string {
	var  []string
	for ,  := range .history[:.gossip] {
		for ,  := range  {
			if .topic ==  {
				 = append(, .mid)
			}
		}
	}
	return 
}

func ( *MessageCache) () {
	 := .history[len(.history)-1]
	for ,  := range  {
		delete(.msgs, .mid)
		delete(.peertx, .mid)
	}
	for  := len(.history) - 2;  >= 0; -- {
		.history[+1] = .history[]
	}
	.history[0] = nil
}