// ****************************************************************************
//
//          Aevol - An in silico experimental evolution platform
//
// ****************************************************************************
//
// Copyright: See the AUTHORS file provided with the package or <www.aevol.fr>
// Web: http://www.aevol.fr/
// E-mail: See <http://www.aevol.fr/contact/>
// Original Authors : Guillaume Beslon, Carole Knibbe, David Parsons
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//
// ****************************************************************************

#include "PhenotypicTarget.h"

#include <iostream>
#include <string>
#include <format>

#include "fuzzy/FuzzyFlavor.h"
#include "io/checkpointing/input_format_error.h"
#include "io/checkpointing/mxifstream.h"
#include "utils/utility.h"

namespace aevol {

auto PhenotypicTarget::make_from_checkpoint(std::ifstream& is, mxifstream& mxis, FuzzyFlavor flavor, size_t sampling)
    -> std::unique_ptr<PhenotypicTarget> {
  auto phenotypic_target = std::make_unique<PhenotypicTarget>();

  phenotypic_target->load_from_checkpoint(is, mxis, flavor, sampling);

  return phenotypic_target;
}

auto PhenotypicTarget::make_from_gaussians(const std::list<Gaussian>& gaussians, FuzzyFlavor flavor, size_t sampling)
    -> std::unique_ptr<PhenotypicTarget> {
  auto phenotypic_target = std::make_unique<PhenotypicTarget>();

  for (const auto& gaussian : gaussians) {
    phenotypic_target->initial_gaussians_.push_back(std::make_unique<Gaussian>(gaussian));
  }
  phenotypic_target->fuzzy_ = PhenotypicTarget::build(phenotypic_target->initial_gaussians_, flavor, sampling);

  return phenotypic_target;
}

void PhenotypicTarget::load_from_checkpoint(std::ifstream& is, mxifstream&, FuzzyFlavor flavor, size_t sampling) {
  std::string str;
  auto nb_pt_constituents = size_t{0};
  get_expected_or_throw(is, "PhenotypicTargetConstituents:", nb_pt_constituents);
  for (auto i = decltype(nb_pt_constituents){0}; i < nb_pt_constituents; ++i) {
    get_expected_or_throw(is, "GAUSSIAN:");
    initial_gaussians_.push_back(Gaussian::make_from_checkpoint(is));
  }
  fuzzy_ = PhenotypicTarget::build(initial_gaussians_, flavor, sampling);
}

void PhenotypicTarget::write_to_checkpoint(std::ofstream&os , mxofstream&) const {
  os << "PhenotypicTargetConstituents: " << initial_gaussians_.size() << "\n";
  for (const auto& gaussian: initial_gaussians_) {
    os << std::format("GAUSSIAN: {:6} {:6} {:6}\n", gaussian->height(), gaussian->mean(), gaussian->width());
  }
}

}  // namespace aevol
