#ifndef LOGISTIC_REGRESSION_H
#define LOGISTIC_REGRESSION_H

#include "abc.h"

namespace liblinear {
#include "liblinear\linear.h"

	//solver types for classification:
	//L2R_LR                L2-regularized logistic regression (primal)
	//L2R_L2LOSS_SVC_DUAL   L2-regularized L2-loss support vector classification (dual)
	//L2R_L2LOSS_SVC        L2-regularized L2-loss support vector classification (primal)
	//L2R_L1LOSS_SVC_DUAL   L2-regularized L1-loss support vector classification (dual)
	//MCSVM_CS              support vector classification by Crammer and Singer
	//L1R_L2LOSS_SVC        L1-regularized L2-loss support vector classification
	//L1R_LR                L1-regularized logistic regression
	//L2R_LR_DUAL           L2-regularized logistic regression (dual)
}



//LIBLINEAR Wrapper
//hardcoded to L2R_LR solver
class LogisticRegression : public ClassifierABC {
private:
    liblinear::problem* _lin_problem = nullptr;
    liblinear::parameter* _lin_parameter = nullptr;
    liblinear::model* _lin_model = nullptr;

    liblinear::problem* _Xy_to_problem(const Matrix<data_t>& data, const vector<label_t>& targets) const;
    liblinear::problem* _Xy_to_problem(const Matrix<data_t>& data, const vector<label_t>& targets, const vector<data_t>& sample_weight) const;
    liblinear::feature_node*  _sample_to_feature_node(const vector<data_t>& sample) const;

protected:
    void _fit(const Matrix<data_t>& data, const vector<label_t>& targets);
    vector<label_t> _predict(const Matrix<data_t>& data) const;
    label_t _predict(const vector<data_t>& sample) const;
public:
    LogisticRegression(double eps = 0.0001, double C = 1.0, int max_iter=1000);
    void fit_(const Matrix<data_t>& data, const vector<label_t>& targets, const vector<data_t>& sample_weight);
	//return maxtrix P where P(i,j) is probability off class j for i-th sample 
    Matrix<double> predict_probabilty(const Matrix<data_t>& data) const;
	//return probability for each class
    vector<double> predict_probabilty(const vector<data_t> sample) const;

	//trained regression coef
	//Matrix with shape (n_classes, n_features() + 1)
	//i-th row - logistic regression for i-th class 
    Matrix<double> coef() const; 
	//logit epsilon getter
	const double eps() const;
	//logit C getter
	const double C() const;
	//logit max_iter getter
	const int max_iter() const;
	//logit sample_weights getter
	const vector<double> sample_weights() const;
	//setters
	LogisticRegression& eps(double val);
	LogisticRegression& C(double val);
	LogisticRegression& max_iter(int val);

    ~LogisticRegression();
};




#endif //LOGISTIC_REGRESSION_H