#pragma once
#include <chrono>
#include "ConcentrationCalibration.hpp"
#include "Configuration.hpp"
#include "vera_base/Spectrum.hpp"

namespace vera
{
struct CalculatedResult
{
  double position;
  double intensity;
  double ppm;
  Ptr<Spectrum> difference;
  Ptr<Spectrum> smoothed;
  Ptr<Spectrum> base;

  void saveTagged(
    std::string const& experimentId, std::chrono::duration<float> duration);
};

class Calculator
{
public:
  virtual ~Calculator() = default;
  virtual CalculatedResult from(Ptr<Spectrum> const& nullMeasurement,
    Ptr<Spectrum> const& sampleMeasurement) const = 0;
};

class HighPassCalculator : public Calculator
{
public:
  HighPassCalculator(ConcentrationCalibration calibration, double smoothing,
    double peakPosition);

  CalculatedResult from(Ptr<Spectrum> const& nullMeasurement,
    Ptr<Spectrum> const& sampleMeasurement) const override;

private:
  ConcentrationCalibration mCalibration;
  double mSmoothing;
  double mPeakPosition;
};

class BaseLineCalculator : public Calculator
{
public:
  BaseLineCalculator(ConcentrationCalibration calibration, double smoothing,
    double peakPosition, double peakSearchWidth, double peakIsolation);

  CalculatedResult from(Ptr<Spectrum> const& nullMeasurement,
    Ptr<Spectrum> const& sampleMeasurement) const override;

private:
  ConcentrationCalibration mCalibration;
  double mSmoothing;
  double mPeakPosition;
  double mPeakSearchWidth;
  double mPeakIsolation;
};

std::unique_ptr<Calculator> makeCalculatorFromConfig(
  GeneralConfiguration const& config);
}  // namespace vera
