package main

import (
	"bytes"
	"flag"
	"log"
	"net/http"
	"strconv"

	// install profile and debug handlers
	_ "code.justin.tv/common/chitin"

	"code.justin.tv/rhys/nursery/ldb"
	"github.com/syndtr/goleveldb/leveldb"
	"github.com/syndtr/goleveldb/leveldb/opt"
	"github.com/syndtr/goleveldb/leveldb/util"
)

var (
	dbPath   = flag.String("db", "", "Path to DB directory")
	prefix   = flag.String("prefix", "", "Key prefix")
	rec      = flag.Bool("recover", false, "Recover DB")
	compact  = flag.Bool("compact", false, "Compact DB")
	hostport = flag.String("http", "127.0.0.1:8080", "HTTP debug host and port")
)

func main() {
	flag.Parse()

	log.SetFlags(log.LUTC | log.Ldate | log.Ltime)

	go func() {
		err := (&http.Server{
			Addr: *hostport,
		}).ListenAndServe()
		if err != nil {
			log.Fatalf("http err=%q", err)
		}
	}()

	o := &opt.Options{
		ErrorIfMissing: true,
		ReadOnly:       !*compact,
		Comparer:       ldb.FastBytewiseComparator,
	}
	var db *leveldb.DB
	var err error
	if *rec {
		db, err = leveldb.RecoverFile(*dbPath, o)
	} else {
		db, err = leveldb.OpenFile(*dbPath, o)
	}
	if err != nil {
		log.Fatalf("db open err=%q", err)
	}
	defer func() {
		err := db.Close()
		if err != nil {
			log.Printf("db close err=%q", err)
		}
	}()

	if *compact {
		err := db.CompactRange(*util.BytesPrefix(nil))
		if err != nil {
			log.Fatalf("CompactRange err=%q", err)
		}
	}

	// prop, err := db.GetProperty("leveldb.sstables")
	// if err != nil {
	// 	log.Fatalf("GetProperty err=%q", err)
	// }
	// log.Fatalf("property \n%s", prop)

	it := db.NewIterator(util.BytesPrefix([]byte(*prefix)), nil)
	var i, nk, nv, z int64
	for it.Next() {
		i++
		nk += int64(len(it.Key()))
		nv += int64(len(it.Value()))
		if i > z {
			log.Printf("i=%d nk=%d nv=%d key %s", i, nk, nv, it.Key())
			z = z*2 + 1
		}
		if true {
			continue
		}

		parts := bytes.SplitN(it.Key(), []byte(" "), 5)
		if len(parts) < 5 {
			continue
		}

		svc, err := strconv.Unquote(string(parts[1]))
		if err != nil {
			continue
		}
		host, err := strconv.Unquote(string(parts[2]))
		if err != nil {
			continue
		}
		pid, err := strconv.ParseInt(string(parts[3]), 10, 32)
		if err != nil {
			continue
		}
		txid := parts[4]

		log.Printf("svc=%q host=%q pid=%d txid=%.16x",
			svc, host, pid, txid)
	}
	log.Printf("i=%d nk=%d nv=%d", i, nk, nv)
	it.Release()
}
