package main

import (
	"flag"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"sort"
	"time"

	"code.justin.tv/common/chitin"
	_ "code.justin.tv/common/golibs/bininfo"
)

func main() {
	var period time.Duration
	flag.DurationVar(&period, "period", 10*time.Second, "Delay between cleanup cycles")
	var reportCount int
	flag.IntVar(&reportCount, "keep", 300, "Number of reports to keep")
	var reportDir string
	flag.StringVar(&reportDir, "reports", "", "Path to reports directory")
	flag.Parse()

	err := chitin.ExperimentalTraceProcessOptIn()
	if err != nil {
		log.Fatalf("trace enable err=%q", err)
	}

	// we'll do the cleanup periodically
	tick := time.NewTimer(period)
	defer tick.Stop()
	// the first run should happen immediately
	tick.Reset(1 * time.Nanosecond)

	for {
		// time to go!
		<-tick.C
		// TODO: jitter
		tick.Reset(period)

		task := cleanupTask{
			reportCount: reportCount,
			reportDir:   reportDir,
		}

		err := task.run()
		if err != nil {
			log.Printf("cleanup err=%q", err)
		}
	}
}

type cleanupTask struct {
	reportCount int
	reportDir   string
}

func (task *cleanupTask) run() error {
	log.Printf("cleanup-state=%q", "begin")
	defer log.Printf("cleanup-state=%q", "end")

	log.Printf("visit dir=%q", task.reportDir)
	if task.reportDir != "" {
		err := cleanupByCount(task.reportDir, task.reportCount)
		if err != nil {
			return err
		}
	}

	return nil
}

func cleanupByCount(dir string, keep int) error {
	infos, err := ioutil.ReadDir(dir)
	if err != nil {
		return err
	}
	sort.Sort(sort.Reverse(fileInfoByTime(infos)))

	var keeping int
	for _, info := range infos {
		fullname := filepath.Join(dir, info.Name())
		if keeping < keep {
			log.Printf("keep=%q", fullname)
			keeping++
			continue
		}
		log.Printf("delete=%q", fullname)
		err := os.RemoveAll(fullname)
		if err != nil {
			return err
		}
	}

	return nil
}

type fileInfoByTime []os.FileInfo

func (l fileInfoByTime) Len() int           { return len(l) }
func (l fileInfoByTime) Less(i, j int) bool { return l[i].ModTime().Before(l[j].ModTime()) }
func (l fileInfoByTime) Swap(i, j int)      { l[i], l[j] = l[j], l[i] }
