import { dirname, join, default as pathModule } from 'path';
import { fileURLToPath } from 'url';
import loadNAPI from 'node-gyp-build-optional-packages';
export let Env,
	Txn,
	Dbi,
	Compression,
	Cursor,
	getAddress,
	getBufferAddress,
	createBufferForAddress,
	clearKeptObjects,
	globalBuffer,
	setGlobalBuffer,
	arch,
	fs,
	os,
	onExit,
	isLittleEndian,
	tmpdir,
	lmdbError,
	path,
	EventEmitter,
	orderedBinary,
	MsgpackrEncoder,
	WeakLRUCache,
	setEnvMap,
	getEnvMap,
	getByBinary,
	detachBuffer,
	startRead,
	setReadCallback,
	write,
	position,
	iterate,
	prefetch,
	resetTxn,
	getCurrentValue,
	getCurrentShared,
	getStringByBinary,
	getSharedByBinary,
	getSharedBuffer,
	compress,
	directWrite,
	getUserSharedBuffer,
	notifyUserCallbacks,
	attemptLock,
	unlock,
	version;
path = pathModule;
let dirName = dirname(fileURLToPath(import.meta.url)).replace(/dist$/, '');
export let nativeAddon = loadNAPI(dirName);

if (process.isBun && false) {
	const { linkSymbols, FFIType } = require('bun:ffi');
	let lmdbLib = linkSymbols({
		getByBinary: {
			args: [FFIType.f64, FFIType.u32],
			returns: FFIType.u32,
			ptr: nativeAddon.getByBinaryPtr,
		},
		iterate: {
			args: [FFIType.f64],
			returns: FFIType.i32,
			ptr: nativeAddon.iteratePtr,
		},
		position: {
			args: [FFIType.f64, FFIType.u32, FFIType.u32, FFIType.u32, FFIType.f64],
			returns: FFIType.i32,
			ptr: nativeAddon.positionPtr,
		},
		write: {
			args: [FFIType.f64, FFIType.f64],
			returns: FFIType.i32,
			ptr: nativeAddon.writePtr,
		},
		resetTxn: {
			args: [FFIType.f64],
			returns: FFIType.void,
			ptr: nativeAddon.resetTxnPtr,
		},
	});
	for (let key in lmdbLib.symbols) {
		nativeAddon[key] = lmdbLib.symbols[key].native;
	}
}
setNativeFunctions(nativeAddon);

export function setNativeFunctions(externals) {
	Env = externals.Env;
	Txn = externals.Txn;
	Dbi = externals.Dbi;
	Compression = externals.Compression;
	getAddress = externals.getAddress;
	getBufferAddress = externals.getBufferAddress;
	createBufferForAddress = externals.createBufferForAddress;
	clearKeptObjects = externals.clearKeptObjects || function () {};
	getByBinary = externals.getByBinary;
	detachBuffer = externals.detachBuffer;
	startRead = externals.startRead;
	setReadCallback = externals.setReadCallback;
	setGlobalBuffer = externals.setGlobalBuffer;
	globalBuffer = externals.globalBuffer;
	getSharedBuffer = externals.getSharedBuffer;
	prefetch = externals.prefetch;
	iterate = externals.iterate;
	position = externals.position;
	resetTxn = externals.resetTxn;
	directWrite = externals.directWrite;
	getUserSharedBuffer = externals.getUserSharedBuffer;
	notifyUserCallbacks = externals.notifyUserCallbacks;
	attemptLock = externals.attemptLock;
	unlock = externals.unlock;
	getCurrentValue = externals.getCurrentValue;
	getCurrentShared = externals.getCurrentShared;
	getStringByBinary = externals.getStringByBinary;
	getSharedByBinary = externals.getSharedByBinary;
	write = externals.write;
	compress = externals.compress;
	Cursor = externals.Cursor;
	lmdbError = externals.lmdbError;
	version = externals.version;
	if (externals.tmpdir) tmpdir = externals.tmpdir;
}
export function setExternals(externals) {
	arch = externals.arch;
	fs = externals.fs;
	EventEmitter = externals.EventEmitter;
	orderedBinary = externals.orderedBinary;
	MsgpackrEncoder = externals.MsgpackrEncoder;
	WeakLRUCache = externals.WeakLRUCache;
	tmpdir = externals.tmpdir;
	os = externals.os;
	onExit = externals.onExit;
	isLittleEndian = externals.isLittleEndian;
}
