/*!
*  Copyright (c) 2016 by Contributors
* \file base.h
* \brief metrics defined
* \author Zhang Chen
*/

#ifndef CPP_PACKAGE_INCLUDE_MXNET_CPP_METRIC_H_
#define CPP_PACKAGE_INCLUDE_MXNET_CPP_METRIC_H_

#include <cmath>
#include <string>
#include <vector>
#include <algorithm>
#include "mxnet-cpp/ndarray.h"
#include "dmlc/logging.h"

namespace mxnet {
namespace cpp {

class EvalMetric {
 public:
  explicit EvalMetric(const std::string& name, int num = 0)
      : name(name), num(num) {}
  virtual void Update(NDArray labels, NDArray preds) = 0;
  void Reset() {
    num_inst = 0;
    sum_metric = 0.0f;
  }
  float Get() { return sum_metric / num_inst; }
  void GetNameValue();

 protected:
  std::string name;
  int num;
  float sum_metric = 0.0f;
  int num_inst = 0;

  static void CheckLabelShapes(NDArray labels, NDArray preds,
                               bool strict = false) {
    if (strict) {
      CHECK_EQ(Shape(labels.GetShape()), Shape(preds.GetShape()));
    } else {
      CHECK_EQ(labels.Size(), preds.Size());
    }
  }
};

class Accuracy : public EvalMetric {
 public:
  Accuracy() : EvalMetric("accuracy") {}

  void Update(NDArray labels, NDArray preds) override {
    CHECK_EQ(labels.GetShape().size(), 1);
    mx_uint len = labels.GetShape()[0];
    std::vector<mx_float> pred_data(len);
    std::vector<mx_float> label_data(len);
    preds.ArgmaxChannel().SyncCopyToCPU(&pred_data, len);
    labels.SyncCopyToCPU(&label_data, len);
    for (mx_uint i = 0; i < len; ++i) {
      sum_metric += (pred_data[i] == label_data[i]) ? 1 : 0;
      num_inst += 1;
    }
  }
};

class LogLoss : public EvalMetric {
 public:
  LogLoss() : EvalMetric("logloss") {}

  void Update(NDArray labels, NDArray preds) override {
    static const float epsilon = 1e-15;
    mx_uint len = labels.GetShape()[0];
    mx_uint m = preds.GetShape()[1];
    std::vector<mx_float> pred_data(len * m);
    std::vector<mx_float> label_data(len);
    preds.SyncCopyToCPU(&pred_data, pred_data.size());
    labels.SyncCopyToCPU(&label_data, len);
    for (mx_uint i = 0; i < len; ++i) {
      sum_metric +=
          -std::log(std::max(pred_data[i * m + label_data[i]], epsilon));
      num_inst += 1;
    }
  }
};

class MAE : public EvalMetric {
 public:
  MAE() : EvalMetric("mae") {}

  void Update(NDArray labels, NDArray preds) override {
    CheckLabelShapes(labels, preds);

    std::vector<mx_float> pred_data;
    preds.SyncCopyToCPU(&pred_data);
    std::vector<mx_float> label_data;
    labels.SyncCopyToCPU(&label_data);

    size_t len = preds.Size();
    mx_float sum = 0;
    for (size_t i = 0; i < len; ++i) {
      sum += std::abs(pred_data[i] - label_data[i]);
    }
    sum_metric += sum / len;
    ++num_inst;
  }
};

class MSE : public EvalMetric {
 public:
  MSE() : EvalMetric("mse") {}

  void Update(NDArray labels, NDArray preds) override {
    CheckLabelShapes(labels, preds);

    std::vector<mx_float> pred_data;
    preds.SyncCopyToCPU(&pred_data);
    std::vector<mx_float> label_data;
    labels.SyncCopyToCPU(&label_data);

    size_t len = preds.Size();
    mx_float sum = 0;
    for (size_t i = 0; i < len; ++i) {
      mx_float diff = pred_data[i] - label_data[i];
      sum += diff * diff;
    }
    sum_metric += sum / len;
    ++num_inst;
  }
};

class RMSE : public EvalMetric {
 public:
  RMSE() : EvalMetric("rmse") {}

  void Update(NDArray labels, NDArray preds) override {
    CheckLabelShapes(labels, preds);

    std::vector<mx_float> pred_data;
    preds.SyncCopyToCPU(&pred_data);
    std::vector<mx_float> label_data;
    labels.SyncCopyToCPU(&label_data);

    size_t len = preds.Size();
    mx_float sum = 0;
    for (size_t i = 0; i < len; ++i) {
      mx_float diff = pred_data[i] - label_data[i];
      sum += diff * diff;
    }
    sum_metric += std::sqrt(sum / len);
    ++num_inst;
  }
};

class PSNR : public EvalMetric {
 public:
  PSNR() : EvalMetric("psnr") {
  }

  void Update(NDArray labels, NDArray preds) override {
    CheckLabelShapes(labels, preds);

    std::vector<mx_float> pred_data;
    preds.SyncCopyToCPU(&pred_data);
    std::vector<mx_float> label_data;
    labels.SyncCopyToCPU(&label_data);

    size_t len = preds.Size();
    mx_float sum = 0;
    for (size_t i = 0; i < len; ++i) {
      mx_float diff = pred_data[i] - label_data[i];
      sum += diff * diff;
    }
    mx_float mse = sum / len;
    if (mse > 0) {
      sum_metric += 10 * std::log(255.0f / mse) / log10_;
    } else {
      sum_metric += 99.0f;
    }
    ++num_inst;
  }

 private:
  mx_float log10_ = std::log(10.0f);
};

}  // namespace cpp
}  // namespace mxnet

#endif  // CPP_PACKAGE_INCLUDE_MXNET_CPP_METRIC_H_

