package filedb

import (
	"regexp"

	"github.com/syndtr/goleveldb/leveldb"
	"github.com/syndtr/goleveldb/leveldb/filter"
	"github.com/syndtr/goleveldb/leveldb/opt"
	"gitlab.com/olanguage/olang/object"
)

type Filedb struct {
	Filename string
}

func New(filename string) *Filedb {
	fdb := &Filedb{Filename: filename}
	return fdb
}

func (fdb *Filedb) Create() *leveldb.DB {
	o := &opt.Options{
		Filter: filter.NewBloomFilter(10),
	}
	db, _ := leveldb.OpenFile(fdb.Filename, o)
	defer db.Close()
	return db
}

func (fdb *Filedb) Store(key string, value string) {
	o := &opt.Options{
		Filter: filter.NewBloomFilter(10),
	}
	db, _ := leveldb.OpenFile(fdb.Filename, o)
	db.Put([]byte(key), []byte(value), nil)
	defer db.Close()
}

func (fdb *Filedb) Get(key string) *object.String {
	o := &opt.Options{
		Filter: filter.NewBloomFilter(10),
	}
	db, _ := leveldb.OpenFile(fdb.Filename, o)
	data, _ := db.Get([]byte(key), nil)

	defer db.Close()

	return &object.String{Value: string(data)}
}

func (fdb *Filedb) Update(key string, value string) {
	fdb.Store(key, value)
}

func (fdb *Filedb) Delete(key string) {
	o := &opt.Options{
		Filter: filter.NewBloomFilter(10),
	}
	db, _ := leveldb.OpenFile(fdb.Filename, o)
	db.Delete([]byte(key), nil)

	defer db.Close()
}

func (fdb *Filedb) Find(search string) map[string]string {
	find := make(map[string]string)
	var re = regexp.MustCompile(`(?i)` + search)
	o := &opt.Options{
		Filter: filter.NewBloomFilter(10),
	}
	db, _ := leveldb.OpenFile(fdb.Filename, o)
	iter := db.NewIterator(nil, nil)
	for iter.Next() {
		key := iter.Key()
		value := iter.Value()

		for range re.FindAllString(string(value), -1) {
			find[string(key)] = string(value)
		}
		for range re.FindAllString(string(key), -1) {
			find[string(key)] = string(value)
		}
	}
	iter.Release()

	defer db.Close()
	return find
}
