//---------------------------------------------------------------------------

#ifndef UCppModelWrapperH
#define UCppModelWrapperH
//---------------------------------------------------------------------------
#endif


#include <windows.h>
#include <System.hpp>

//looper classifier handle
#define LOOPER_CLF_H void*
//frame handle
#define CONTROL_FRAME_H void*

typedef void(*ReportProgressCallback)(CONTROL_FRAME_H, float);
typedef void(*FinishedCallback)(CONTROL_FRAME_H);
typedef void(*MessageCallback)(CONTROL_FRAME_H, const char* str);

struct InteropNegotiator {
	ReportProgressCallback report_progress;
	FinishedCallback finished;
	MessageCallback message;
	CONTROL_FRAME_H control_frame_handle;
};

typedef LOOPER_CLF_H (*init_LooperClf_fptr)(const char*);
typedef int (*kill_LooperClf_fptr)(LOOPER_CLF_H);
typedef int (*LooperClf_predict_fptr)(LOOPER_CLF_H LooperClf, const double *data, unsigned n_samples, int* y_pred);
typedef int (*LooperClf_optimize_weights_fptr)(LOOPER_CLF_H LooperClf);
typedef int (*LooperClf_optimize_params_fptr)(LOOPER_CLF_H LooperClf);
typedef int (*LooperClf_cross_val_report_fptr)(LOOPER_CLF_H LooperClf);
typedef int (*LooperClf_save_to_fptr)(LOOPER_CLF_H LooperClf, const char* filename);
typedef int (*LooperClf_get_info_fptr)(LOOPER_CLF_H LooperClf, char* out);
typedef int (*LooperClf_set_negotiator_fptr)(LOOPER_CLF_H LooperClf, const InteropNegotiator* report_progress);
typedef int (*LooperClf_cancel_fptr)(LOOPER_CLF_H LooperClf);
typedef int (*LooperClf_n_features_fptr)(LOOPER_CLF_H LooperClf, unsigned* n_features);

class TCppModelWrapper
{
  LOOPER_CLF_H LooperClfH;
  HINSTANCE CppModelDLLH;

  init_LooperClf_fptr _init_LooperClf;
  kill_LooperClf_fptr _kill_LooperClf;
  LooperClf_predict_fptr _LooperClf_predict;
  LooperClf_optimize_weights_fptr _LooperClf_optimize_weights;
  LooperClf_optimize_params_fptr _LooperClf_optimize_params;
  LooperClf_cross_val_report_fptr _LooperClf_cross_val_report;
  LooperClf_save_to_fptr _LooperClf_save_to;
  LooperClf_get_info_fptr _LooperClf_get_info;
  LooperClf_set_negotiator_fptr _LooperClf_set_negotiator;
  LooperClf_cancel_fptr _LooperClf_cancel;
  LooperClf_n_features_fptr _LooperClf_n_features;

  TCppModelWrapper& operator=(const TCppModelWrapper&);
  TCppModelWrapper(const TCppModelWrapper& obj);
  void _loadDll();
public:
  const static wchar_t* CppModelDLLFileName;
  const static char* LooperClfFileName;
  TCppModelWrapper();
  TCppModelWrapper(const char* filename);
  ~TCppModelWrapper();
  bool IsOk();
	/*
	data - n_samples x n_features matrix, row major order
    to get expected number of features use NumFeatures()
	yPredicted - allocated int array (with length equals to numSamples)
	returns 0 if did not fail
	*/
  int Predict(const double *data, unsigned numSamples, int* yPredicted);
  unsigned NumFeatures();
  int OptimizeWeights();
  int OptimizeParams();
  int CrossValReport();
  int SaveTo(const char* filename);
  int Load(const char* filename);
  UnicodeString GetInfo(unsigned BufferSize=100000);
  int SetNegotiator(const InteropNegotiator& negotiator);
  int Cancel();

};
