package main

import (
	"bytes"
	"sync"
)

var maxBacklog = 64 * 1024 // Tests override this.

// rollingLog is an io.Writer that buffers all data written to it, purging
// earlier entries to maintain a buffer size of maxBacklog bytes.
// Its methods are safe for concurrent use.
type rollingLog struct {
	mu  sync.Mutex
	buf []byte
}

func (l *rollingLog) Write(b []byte) (int, error) {
	l.mu.Lock()
	defer l.mu.Unlock()
	if len(b) >= maxBacklog {
		l.buf = append(l.buf[:0], b...)
		return len(b), nil
	}
	if len(l.buf)+len(b) > maxBacklog {
		// Make room for b.
		i := len(b)
		if len(l.buf) > maxBacklog {
			i += len(l.buf) - maxBacklog
		}
		b2 := l.buf[i:]
		// Start at the first line feed,
		// so that we don't keep partial lines.
		if i := bytes.IndexByte(b2, '\n'); i >= 0 {
			b2 = b2[i+1:]
		}
		// Replace buffer.
		l.buf = append(l.buf[:0], b2...)
	}
	l.buf = append(l.buf, b...)
	return len(b), nil
}

// Log returns a copy of the log buffer.
func (l *rollingLog) Log() []byte {
	l.mu.Lock()
	defer l.mu.Unlock()
	return append([]byte(nil), l.buf...)
}
