package gorocksdb

// #include <stdlib.h>
// #include "rocksdb/c.h"
import "C"

import (
	"errors"
	"unsafe"
)

// SSTFileWriter is used to create sst files that can be added to database later.
// All keys in files generated by SstFileWriter will have sequence number = 0.
type SSTFileWriter struct {
	c *C.rocksdb_sstfilewriter_t
}

// NewSSTFileWriter creates an SSTFileWriter object.
func NewSSTFileWriter(opts *EnvOptions, dbOpts *Options) *SSTFileWriter {
	c := C.rocksdb_sstfilewriter_create(opts.c, dbOpts.c)
	return &SSTFileWriter{c: c}
}

// Open prepares SstFileWriter to write into file located at "path".
func (w *SSTFileWriter) Open(path string) error {
	var (
		cErr  *C.char
		cPath = C.CString(path)
	)
	defer C.free(unsafe.Pointer(cPath))
	C.rocksdb_sstfilewriter_open(w.c, cPath, &cErr)
	if cErr != nil {
		defer C.rocksdb_free(unsafe.Pointer(cErr))
		return errors.New(C.GoString(cErr))
	}
	return nil
}

// Add adds key, value to currently opened file.
// REQUIRES: key is after any previously added key according to comparator.
func (w *SSTFileWriter) Add(key, value []byte) error {
	cKey := byteToChar(key)
	cValue := byteToChar(value)
	var cErr *C.char
	C.rocksdb_sstfilewriter_add(w.c, cKey, C.size_t(len(key)), cValue, C.size_t(len(value)), &cErr)
	if cErr != nil {
		defer C.rocksdb_free(unsafe.Pointer(cErr))
		return errors.New(C.GoString(cErr))
	}
	return nil
}

// Finish finishes writing to sst file and close file.
func (w *SSTFileWriter) Finish() error {
	var cErr *C.char
	C.rocksdb_sstfilewriter_finish(w.c, &cErr)
	if cErr != nil {
		defer C.rocksdb_free(unsafe.Pointer(cErr))
		return errors.New(C.GoString(cErr))
	}
	return nil
}

// Destroy destroys the SSTFileWriter object.
func (w *SSTFileWriter) Destroy() {
	C.rocksdb_sstfilewriter_destroy(w.c)
}
