package examples

import "core:fmt"
import "core:log"
import "core:mem"
import "core:os"
import "core:sys/posix"

import mdb "../../lmdb"

// 0o660
DB_MODE :: posix.mode_t{.IWGRP, .IRGRP, .IWUSR, .IRUSR}
DB_PATH :: "out/debug/lmdb_example_db"

main :: proc() {
	//----- General setup ----------------------------------
	// Temp
	track_temp: mem.Tracking_Allocator
	mem.tracking_allocator_init(&track_temp, context.temp_allocator)
	context.temp_allocator = mem.tracking_allocator(&track_temp)

	// Default
	track: mem.Tracking_Allocator
	mem.tracking_allocator_init(&track, context.allocator)
	context.allocator = mem.tracking_allocator(&track)
	// Log a warning about any memory that was not freed by the end of the program.
	// This could be fine for some global state or it could be a memory leak.
	defer {
		// Temp allocator
		if len(track_temp.bad_free_array) > 0 {
			fmt.eprintf("=== %v incorrect frees - temp allocator: ===\n", len(track_temp.bad_free_array))
			for entry in track_temp.bad_free_array {
				fmt.eprintf("- %p @ %v\n", entry.memory, entry.location)
			}
			mem.tracking_allocator_destroy(&track_temp)
		}
		// Default allocator
		if len(track.allocation_map) > 0 {
			fmt.eprintf("=== %v allocations not freed - main allocator: ===\n", len(track.allocation_map))
			for _, entry in track.allocation_map {
				fmt.eprintf("- %v bytes @ %v\n", entry.size, entry.location)
			}
		}
		if len(track.bad_free_array) > 0 {
			fmt.eprintf("=== %v incorrect frees - main allocator: ===\n", len(track.bad_free_array))
			for entry in track.bad_free_array {
				fmt.eprintf("- %p @ %v\n", entry.memory, entry.location)
			}
		}
		mem.tracking_allocator_destroy(&track)
	}
	// Logger
	context.logger = log.create_console_logger()
	defer log.destroy_console_logger(context.logger)


	environment: ^mdb.Env

	// Create environment for lmdb
	mdb.panic_on_err(mdb.env_create(&environment))
	// Create directory for databases. Won't do anything if it already exists.
	os.make_directory(DB_PATH)
	// Open the database files (creates them if they don't already exist)
	mdb.panic_on_err(mdb.env_open(environment, DB_PATH, {}, DB_MODE))

	// Transactions
	txn_handle: ^mdb.Txn
	db_handle: mdb.Dbi
	// Put transaction
	key := 7
	key_val := mdb.pod_val(&key)
	put_data := 12
	put_data_val := mdb.pod_val(&put_data)
	mdb.panic_on_err(mdb.txn_begin(environment, nil, {}, &txn_handle))
	mdb.panic_on_err(mdb.dbi_open(txn_handle, nil, {}, &db_handle))
	mdb.panic_on_err(mdb.put(txn_handle, db_handle, &key_val, &put_data_val, {}))
	mdb.panic_on_err(mdb.txn_commit(txn_handle))

	// Get transaction
	data_val: mdb.Val
	mdb.panic_on_err(mdb.txn_begin(environment, nil, {}, &txn_handle))
	mdb.panic_on_err(mdb.get(txn_handle, db_handle, &key_val, &data_val))
	data_cpy := mdb.pod_copy(data_val, int)
	mdb.txn_abort(txn_handle)
	fmt.println("Get result:", data_cpy)
}
