package fstree

import (
	"sync"
)

// FileCounter used to count files in FSTree. The implementation must be thread-safe.
type FileCounter interface {
	Set(count, size uint64)
	Inc(size uint64)
	Dec(size uint64)
}

type noopCounter struct{}

func (c *noopCounter) Set(uint64, uint64) {}
func (c *noopCounter) Inc(uint64)         {}
func (c *noopCounter) Dec(uint64)         {}

func counterEnabled(c FileCounter) bool {
	_, noop := c.(*noopCounter)
	return !noop
}

type SimpleCounter struct {
	mtx   sync.RWMutex
	count uint64
	size  uint64
}

func NewSimpleCounter() *SimpleCounter {
	return &SimpleCounter{}
}

func (c *SimpleCounter) Set(count, size uint64) {
	c.mtx.Lock()
	defer c.mtx.Unlock()

	c.count = count
	c.size = size
}

func (c *SimpleCounter) Inc(size uint64) {
	c.mtx.Lock()
	defer c.mtx.Unlock()

	c.count++
	c.size += size
}

func (c *SimpleCounter) Dec(size uint64) {
	c.mtx.Lock()
	defer c.mtx.Unlock()

	if c.count > 0 {
		c.count--
	} else {
		panic("fstree.SimpleCounter: invalid count")
	}
	if c.size >= size {
		c.size -= size
	} else {
		panic("fstree.SimpleCounter: invalid size")
	}
}

func (c *SimpleCounter) CountSize() (uint64, uint64) {
	c.mtx.RLock()
	defer c.mtx.RUnlock()

	return c.count, c.size
}