package kv

import (
	"github.com/cockroachdb/pebble"
)

var Impl *KvImpl

type KvImpl struct {
	PebbleDB *pebble.DB
}

func NewPebble(datadir string) *KvImpl {
	db, err := pebble.Open(datadir, &pebble.Options{})
	if err != nil {
		panic(err)
	}
	return &KvImpl{
		PebbleDB: db,
	}
}

func (db *KvImpl) PebbleSet(key, val string) error {
	return db.PebbleDB.Set([]byte(key), []byte(val), pebble.Sync)
}

func (db *KvImpl) PebbleGet(key string) ([]byte, error) {
	value, _, err := db.PebbleDB.Get([]byte(key))
	if err != nil {
		return nil, err
	}

	return value, nil
}

func (db *KvImpl) PebbleFetch(prefixKey string) (result map[string]string, err error) {
	keyUpperBound := func(b []byte) []byte {
		end := make([]byte, len(b))
		copy(end, b)
		for i := len(end) - 1; i >= 0; i-- {
			end[i] = end[i] + 1
			if end[i] != 0 {
				return end[:i+1]
			}
		}
		return nil // no upper-bound
	}

	prefixIterOptions := func(prefix []byte) *pebble.IterOptions {
		return &pebble.IterOptions{
			LowerBound: prefix,
			UpperBound: keyUpperBound(prefix),
		}
	}

	iter, err := db.PebbleDB.NewIter(prefixIterOptions([]byte(prefixKey)))

	if err != nil {
		return nil, err
	}

	for iter.First(); iter.Valid(); iter.Next() {
		result[string(iter.Key())] = string(iter.Value())
	}
	return
}