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

#pragma hdrstop

#include "UCppModelWrapper.h"
#include <System.IOUtils.hpp>
// ---------------------------------------------------------------------------
#pragma package(smart_init)

const wchar_t* TCppModelWrapper::CppModelDLLFileName = L"CppModel.dll";
const char* TCppModelWrapper::LooperClfFileName = "looper_clf.xml";

void TCppModelWrapper::_loadDll()
  {
  CppModelDLLH = LoadLibrary(CppModelDLLFileName);
  if (CppModelDLLH)
    {
    _init_LooperClf = (init_LooperClf_fptr)GetProcAddress(CppModelDLLH, "init_LooperClf");
	_kill_LooperClf = (kill_LooperClf_fptr)GetProcAddress(CppModelDLLH, "kill_LooperClf");
    _LooperClf_predict = (LooperClf_predict_fptr)GetProcAddress(CppModelDLLH, "LooperClf_predict");
    _LooperClf_optimize_weights = (LooperClf_optimize_weights_fptr)GetProcAddress(CppModelDLLH, "LooperClf_optimize_weights");
    _LooperClf_optimize_params = (LooperClf_optimize_params_fptr)GetProcAddress(CppModelDLLH, "LooperClf_optimize_params");
	_LooperClf_cross_val_report = (LooperClf_cross_val_report_fptr)GetProcAddress(CppModelDLLH, "LooperClf_cross_val_report");
    _LooperClf_save_to = (LooperClf_save_to_fptr)GetProcAddress(CppModelDLLH, "LooperClf_save_to");
    _LooperClf_get_info = (LooperClf_get_info_fptr)GetProcAddress(CppModelDLLH, "LooperClf_get_info");
	_LooperClf_set_negotiator = (LooperClf_set_negotiator_fptr)GetProcAddress(CppModelDLLH, "LooperClf_set_negotiator");
	_LooperClf_cancel = (LooperClf_cancel_fptr)GetProcAddress(CppModelDLLH, "LooperClf_cancel");
	_LooperClf_n_features = (LooperClf_n_features_fptr)GetProcAddress(CppModelDLLH, "LooperClf_n_features");
    }
  }

// ---------------------------------------------------------------------------
TCppModelWrapper::TCppModelWrapper()
  {
  _loadDll();
  LooperClfH = _init_LooperClf(LooperClfFileName);
  }

// ---------------------------------------------------------------------------
TCppModelWrapper::TCppModelWrapper(const char* ClfFilename)
  {
  _loadDll();
  LooperClfH = _init_LooperClf(ClfFilename);
  }

// ---------------------------------------------------------------------------
TCppModelWrapper::~TCppModelWrapper()
  {
  if (LooperClfH)
    {
    _kill_LooperClf(LooperClfH);
    }
  if (CppModelDLLH)
    {
    FreeLibrary(CppModelDLLH);
    }
  }

// ---------------------------------------------------------------------------
bool TCppModelWrapper::IsOk()
  {
  return CppModelDLLH && LooperClfH;
  }

// ---------------------------------------------------------------------------
/*
 data - n_samples x n_features matrix, row major order
 yPredicted - allocated int array (with length equals to numSamples)
 returns 0 if did not fail
 */
int TCppModelWrapper::Predict(const double *data, unsigned numSamples, int* yPredicted)
  {
  if (CppModelDLLH && LooperClfH)
    return _LooperClf_predict(LooperClfH, data, numSamples, yPredicted);
  else
    return 1;
  }
// ---------------------------------------------------------------------------
unsigned TCppModelWrapper::NumFeatures()
{
	unsigned ret = 0;
	if(_LooperClf_n_features(LooperClfH, &ret) == 0)
	{
		return ret;
	}
	else
	{
        return 0;
    }
}
// ---------------------------------------------------------------------------
int TCppModelWrapper::OptimizeWeights()
  {
  if (CppModelDLLH && LooperClfH)
    return _LooperClf_optimize_weights(LooperClfH);
  else
    return 1;
  }

// ---------------------------------------------------------------------------
int TCppModelWrapper::OptimizeParams()
  {
  if (CppModelDLLH && LooperClfH)
    return _LooperClf_optimize_params(LooperClfH);
  else
    return 1;
  }

// ---------------------------------------------------------------------------
int TCppModelWrapper::CrossValReport()
  {
  if (CppModelDLLH && LooperClfH)
	return _LooperClf_cross_val_report(LooperClfH);
  else
    return 1;
  }

// ---------------------------------------------------------------------------
int TCppModelWrapper::SaveTo(const char* filename)
  {
  if (CppModelDLLH && LooperClfH)
    return _LooperClf_save_to(LooperClfH, filename);
  else
    return 1;
  }

// ---------------------------------------------------------------------------
int TCppModelWrapper::Load(const char* filename)
  {
  if (CppModelDLLH)
    {
	_kill_LooperClf(LooperClfH);
	LooperClfH = NULL;
	LooperClfH = _init_LooperClf(filename);
	if (LooperClfH)
      return 0;
    else
      return -1;
    }
  else
    {
    return 1;
    }
  }

// ---------------------------------------------------------------------------
UnicodeString TCppModelWrapper::GetInfo(unsigned BufferSize)
  {
  if (CppModelDLLH && LooperClfH)
    {
    char* buffer = new char[BufferSize];
    _LooperClf_get_info(LooperClfH, buffer);
	UnicodeString res = UnicodeString(buffer);
    delete[]buffer;
    return res;
    }
  else
    {
    return UnicodeString();
    }

  }

int TCppModelWrapper::SetNegotiator(const InteropNegotiator& negotiator)
  {
  if (CppModelDLLH)
    {
    	return _LooperClf_set_negotiator (LooperClfH, &negotiator);
    }
  else
    {
    	return -2;
    }
  }

int TCppModelWrapper::Cancel()
  {
  if (CppModelDLLH)
    {
		return _LooperClf_cancel(LooperClfH);
    }
  else
    {
    return -2;
    }
  }


