// Copyright (C) 2022 Marius Schellenberger

package fs

import (
	"errors"
	"sync"
	"sync/atomic"

	"github.com/go-logr/logr"
)

var InvalidMaxQuota = errors.New("invalid max quota")

type Quota struct {
	mu  sync.Mutex
	log logr.Logger
	fs  *FS
	cur int64
	max int64
}

func NewQuota(cur, max int64, fs *FS, log logr.Logger) (q *Quota, err error) {
	if max <= 0 {
		err = InvalidMaxQuota
		return
	}
	q = &Quota{log: log, fs: fs, cur: cur, max: max}
	q.log.Info("quota usage", "current", q.cur, "max", q.max)
	return
}

func (q *Quota) Usage() (cur, max int64) {
	cur = atomic.LoadInt64(&q.cur)
	max = q.max
	return
}

func (q *Quota) cleanup() {
	if !q.mu.TryLock() {
		return
	}
	q.log.Info("quota usage", "current", atomic.LoadInt64(&q.cur), "max", q.max)
	defer q.mu.Unlock()
	free := q.fs.mh.DeleteOldest()
	atomic.AddInt64(&q.cur, -free)
}

func (q *Quota) Add(n int) {
	if q.max < atomic.AddInt64(&q.cur, int64(n)) {
		q.cleanup()
	}
}
