// ****************************************************************************
//
//          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/>.
//
// ****************************************************************************




// =================================================================
//                              Includes
// =================================================================
#include "SelectionParams.h"

#include "Dna.h"

#include "biochemistry/mutations/mutators/DnaMutator.h"
#include "utility.h"
//#include <math.h>

#ifdef _OPENMP
#include <omp.h>
#endif

#include <chrono>
#include <iostream>

using std::chrono::high_resolution_clock;

namespace aevol {

void SelectionParams::write_to_checkpoint(std::ofstream& os, mxofstream& mxos) const {
  os << "SelectionScheme: " << to_string(selection_scheme_) << ' ' << selection_pressure_ << '\n';
  os << "SelectionScope: " << to_string(selection_scope_) << ' ' << selection_scope_x_ << ' '
     << selection_scope_y_ << '\n';
  #ifdef SEX
  os << "SelfingControl: " << selfing_control_ << '\n';
  if (selfing_control_) {
    os << "SelfingRate: " << selfing_rate_ << '\n';
  }
  #endif
  mxos << "FitnessFunction: " << to_string(fitness_function_) << '\n';
}

void SelectionParams::load_from_checkpoint(std::ifstream& is, mxifstream& mxis) {
  auto str = std::string{};
  get_expected_or_throw(is, "SelectionScheme:", selection_scheme_, selection_pressure_);
  get_expected_or_throw(is, "SelectionScope:", selection_scope_, selection_scope_x_, selection_scope_y_);
  #ifdef SEX
  get_expected_or_throw(is, "SelfingControl:", selfing_control_);
  if (selfing_control_) {
    get_expected_or_throw(is, "SelfingRate:", selfing_rate_);
  }
  #endif
  get_expected_or_throw(mxis, "FitnessFunction:", fitness_function_);
}

std::ostream& operator<<(std::ostream& os, const SelectionParams& obj) {
  os << "SelectionScheme: " << to_string(obj.selection_scheme()) << ' ' << obj.selection_pressure() << '\n';
  os << "SelectionScope: " << to_string(obj.selection_scope()) << ' ' << obj.selection_scope_x() << ' '
     << obj.selection_scope_y() << '\n';
  #ifdef SEX
  os << "SelfingControl: " << obj.selfing_control() << '\n';
  if (obj.selfing_control()) {
    os << "SelfingRate: " << obj.selfing_rate() << '\n';
  }
  #endif
  os << "FitnessFunction: " << to_string(obj.fitness_func()) << '\n';
  return os;
}

} // namespace aevol
