#pragma once
#include <string>
#include <vector>
#include "opencv2/opencv.hpp"

namespace libhnsw {
    enum MODE 
    {
        BRUTE_FORCE_KNN		= 0,
        BRUTE_FORCE_KNN_CF	= 1,
        HNSW_FORCE_KNN		= 2,
        HNSW_FORCE_KNN_CF	= 3,
		MNN_MATMUL_CF		= 4,
		OPENCV_MATMUL_CF	= 5
    };
	enum SPACE_TYPE 
    {
		INNER_PRODUCT=0,
        L1_DISTANCE=1,
        L2_DISTANCE=2,
    };
	struct RequireSample    //��ѯ�����ṹ��
	{
		float* data=NULL;
		int d;             // ����ά�ȣ������0��ʾδ��ѯ��
	};
    class Index
    {

		public:

			// ���캯��1:��ʼ��
			Index(int d, int n, MODE md,SPACE_TYPE st=L2_DISTANCE,
					size_t M = 16, size_t ef_construction = 200, size_t random_seed = 100);

			~Index();

			// ���캯��2:��ʼ��load index������20211224��
			//Index(const std::string index_path,int d, int n, MODE md,SPACE_TYPE st=L2_DISTANCE);
		   
			// ����Index���ɹ�:1��ʧ��:0������20211224��
			int loadIndex(const std::string& location);
			
			// ����һ������
			int Addsample(float *sample, int label);
	
			// ɾ��һ������
			int Removesample(int label);
	
			// ����һ������
			std::vector<std::pair<float, int>> Search(float* sample, int k);
			
			// ��ѯһ����������֧��BRUTEģʽ��
			int Selectsample(RequireSample& sample, int label);
			// �ͷ�һ����ѯ����
			int freeSelectsample(RequireSample* sample);

			// ����index
			void saveIndex(const std::string &location);
			
			// ��ȡindex���������
			int get_max_elements();
			
			// ��ȡindex�ĵ�ǰ����
			int get_cur_element_count();
			
			// ��ֵ����fea_dim_*sizeof(float)
			int get_data_size();

			
		private:
			int fea_dim_;	// ������
			int num_;		// �������
			MODE md_;		// �㷨����
			SPACE_TYPE st_;  // ���㷽ʽ
    };
}