package counters

import (
	"database/sql"

	c "github.com/Azareal/Gosora/common"
	qgen "github.com/Azareal/Gosora/query_gen"
	"github.com/pkg/errors"
)

var RouteViewCounter *DefaultRouteViewCounter

// TODO: Make this lockless?
type DefaultRouteViewCounter struct {
	buckets []*RWMutexCounterBucket //[RouteID]count
	insert  *sql.Stmt
}

func NewDefaultRouteViewCounter(acc *qgen.Accumulator) (*DefaultRouteViewCounter, error) {
	routeBuckets := make([]*RWMutexCounterBucket, len(routeMapEnum))
	for bucketID, _ := range routeBuckets {
		routeBuckets[bucketID] = &RWMutexCounterBucket{counter: 0}
	}
	co := &DefaultRouteViewCounter{
		buckets: routeBuckets,
		insert:  acc.Insert("viewchunks").Columns("count, createdAt, route").Fields("?,UTC_TIMESTAMP(),?").Prepare(),
	}
	c.AddScheduledFifteenMinuteTask(co.Tick) // There could be a lot of routes, so we don't want to be running this every second
	//c.AddScheduledSecondTask(co.Tick)
	c.AddShutdownTask(co.Tick)
	return co, acc.FirstError()
}

func (co *DefaultRouteViewCounter) Tick() error {
	for routeID, routeBucket := range co.buckets {
		var count int
		routeBucket.RLock()
		count = routeBucket.counter
		routeBucket.counter = 0
		routeBucket.RUnlock()

		err := co.insertChunk(count, routeID) // TODO: Bulk insert for speed?
		if err != nil {
			return errors.Wrap(errors.WithStack(err), "route counter")
		}
	}
	return nil
}

func (co *DefaultRouteViewCounter) insertChunk(count int, route int) error {
	if count == 0 {
		return nil
	}
	routeName := reverseRouteMapEnum[route]
	c.DebugLogf("Inserting a vchunk with a count of %d for route %s (%d)", count, routeName, route)
	_, err := co.insert.Exec(count, routeName)
	return err
}

func (co *DefaultRouteViewCounter) Bump(route int) {
	// TODO: Test this check
	c.DebugDetail("co.buckets[", route, "]: ", co.buckets[route])
	if len(co.buckets) <= route || route < 0 {
		return
	}
	co.buckets[route].Lock()
	co.buckets[route].counter++
	co.buckets[route].Unlock()
}