/* Distributed under the Apache License, Version 2.0.
   See accompanying NOTICE file for details.*/

#pragma once

#include "cdm/CommonDefs.h"
#include "cdm/engine/SEDataRequest.h"
#include "cdm/engine/SEEventManager.h"

class CDM_DECL SEValidationTarget : public Loggable
{
  friend class PBValidation;//friend the serialization class
protected:
  SEValidationTarget() { Clear(); }
public:
  virtual ~SEValidationTarget() = default;

  virtual void Clear();
  virtual bool IsValid();

  std::string GetHeader() const { return m_Header; }
  void SetHeader(const std::string& h) { m_Header = h; }

  std::string GetReference() const { return m_Reference; }
  void SetReference(const std::string& c) { m_Reference = c; }

  std::string GetNotes() const { return m_Notes; }
  void SetNotes(const std::string& n) { m_Notes = n; }

  std::string GetTableFormatting() const { return m_TableFormatting; }
  void SetTableFormatting(const std::string& f) { m_TableFormatting = f; }

  std::string GetComputedEnum() const { return m_ComputedEnum; }
  void SetComputedEnum(const std::string& e) { m_ComputedEnum = e; }

  double GetComputedValue() const { return m_ComputedValue; }
  void SetComputedValue(double d) { m_ComputedValue = d; }

  double GetError() const { return m_Error; }
  void SetError(double d) { m_Error = d; }

  double GetGoodPercentError() const { return m_GoodPercentError; }
  void SetGoodPercentError(double e) { m_GoodPercentError = e; }

  double GetFairPercentError() const { return m_FairPercentError; }
  void SetFairPercentError(double e) { m_FairPercentError = e; }

protected:
  std::string                                m_Header;
  std::string                                m_Reference;
  std::string                                m_Notes;
  std::string                                m_TableFormatting;

  std::string                                m_ComputedEnum;
  double                                     m_ComputedValue;
  
  double                                     m_Error;
  double                                     m_GoodPercentError;
  double                                     m_FairPercentError;
};

class CDM_DECL SESegmentValidationTarget : public SEValidationTarget
{
  friend class PBValidation;//friend the serialization class
public:
  SESegmentValidationTarget();
  virtual ~SESegmentValidationTarget() = default;

  static bool SerializeToString(const std::vector<const SESegmentValidationTarget*>& src, std::string& output, eSerializationFormat m, Logger* logger);
  static bool SerializeToFile(const std::vector<const SESegmentValidationTarget*>& src, const std::string& filename, Logger* logger);
  static bool SerializeFromString(const std::string& src, std::vector<SESegmentValidationTarget*>& dst, eSerializationFormat m, Logger* logger);
  static bool SerializeFromFile(const std::string& filename, std::vector<SESegmentValidationTarget*>& dst, Logger* logger);

  void Clear() override;

  std::string GetComparisonFormula() const { return m_ComparisonFormula; }
  void SetComparisonFormula(const std::string& f) { m_ComparisonFormula = f; }

protected:
  std::string m_ComparisonFormula;
};

class CDM_DECL SETimeSeriesValidationTarget : public SEValidationTarget
{
  friend class PBValidation;//friend the serialization class
public:
  enum class eComparisonType { None=0, TargetEnum, TargetValue, TargetRange };
  enum class eTargetType { Mean=0, Minimum, Maximum,
    MeanPerIdealWeight_kg, MaxPerIdealWeight_kg, MinPerIdealWeight_kg, Enumeration };
  SETimeSeriesValidationTarget();
  virtual ~SETimeSeriesValidationTarget() = default;

  void Clear() override;

  static bool SerializeToString(const std::vector<const SETimeSeriesValidationTarget*>&src, std::string& output, eSerializationFormat m, Logger* logger);
  static bool SerializeToFile(const std::vector<const SETimeSeriesValidationTarget*>& src, const std::string& filename, Logger* logger);
  static bool SerializeFromString(const std::string& src, std::vector<SETimeSeriesValidationTarget*>& dst, eSerializationFormat m, Logger* logger);
  static bool SerializeFromFile(const std::string& filename, std::vector<SETimeSeriesValidationTarget*>& dst, Logger* logger);

  eTargetType GetTargetType() const { return m_TargetType; }
  eComparisonType GetComparisonType() const { return m_ComparisonType; }

  void SetAssessment(const std::string& a) { m_Assessment = a; }
  std::string GetAssessment() const { return m_Assessment; }

  void SetPatientSpecific(bool b) { m_PatientSpecific = b; }
  bool GetPatientSpecific() const { return m_PatientSpecific; }

  void SetTargetEnum(const std::string& s);
  std::string GetTargetEnum() const { return m_TargetEnum; }

  void   SetTargetValue(double d, eTargetType t);
  double GetTargetValue() const { return m_TargetValue; }

  void   SetTargetRange(double min, double max, eTargetType t);
  double GetTargetMaximum() const { return m_TargetMaximum; }
  double GetTargetMinimum() const { return m_TargetMinimum; }

  // Maybe we want a different class to do the comparision
  // For now, I just put it in line here for the CircuitOptimizer
  bool ComputeError();
  std::vector<double>& GetData() { return m_Data; }

protected:
  eComparisonType                            m_ComparisonType;
  eTargetType                                m_TargetType;

  std::string                                m_Assessment;
  bool                                       m_PatientSpecific;

  std::string                                m_TargetEnum;
  double                                     m_TargetValue;
  double                                     m_TargetMaximum;
  double                                     m_TargetMinimum;

  // Not serializing
  std::vector<double>                        m_Data;
};
