#pragma once

#include "common.h"
#include "types.h"

class BTreeBase
{
protected:
	typedef int KeyComparsionOp(const void* const key, const void* const sub_data);

	typedef int TraverseCallback(const void* const data, void* const arg);

public:
	enum
	{
		kTRAVERSE_CONTINUE = 0,
		kTRAVERSE_STOP = -1,
	};

	static const uint32_t kINVALID_INDEX = -1;

	inline BTreeBase(const void* const table_data, KeyComparsionOp* const less_than_op, KeyComparsionOp* const equal_op)
		: table_data_(table_data)
		, less_than_op_(less_than_op)
		, equal_op_(equal_op)
	{
	}

	inline virtual ~BTreeBase()
	{
	}

protected:
	template<typename T>
	struct TraverseCallbackArgs
	{
		inline TraverseCallbackArgs(T* const callback, void* const arg)
			: callback(callback)
			, arg(arg)
		{
		}

		T* const callback;
		void* const arg;
	};

	const void* search(const uint32_t index) const;

	const void* search(const void* const key, uint32_t* const index) const;

	void traverse(TraverseCallback* callback, void* const arg) const;

	virtual const void* skip_node_data(const void* const node) const = 0;

	template<typename T>
	static inline KeyComparsionOp* key_comparsion_op(T* op)
	{
		return reinterpret_cast<KeyComparsionOp*>(op);
	}

private:
	const void* search_with_cmp(const void* const node_data, const void* const key, KeyComparsionOp* const op, uint32_t* const lower_bound, uint32_t* const upper_bound, const bool is_internal) const;

	const void* table_data_;

	KeyComparsionOp* const less_than_op_;
	KeyComparsionOp* const equal_op_;
};
