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




// =================================================================
//                              Libraries
// =================================================================



// =================================================================
//                            Project Files
// =================================================================
#include "MutationParams.h"
#include "utility.h"

namespace aevol {

//##############################################################################
//                                                                             #
//                             Class MutationParams                             #
//                                                                             #
//##############################################################################

// =================================================================
//                    Definition of static attributes
// =================================================================

// =================================================================
//                             Constructors
// =================================================================
MutationParams::MutationParams()
{
  // --------------------------------------------------------- Mutation rates
  point_mutation_rate_  = 0.0;
  small_insertion_rate_ = 0.0;
  small_deletion_rate_  = 0.0;
  max_indel_size_       = 0;

  // ------------------------------ Rearrangement rates (without alignements)
  duplication_rate_   = 0.0;
  deletion_rate_      = 0.0;
  translocation_rate_ = 0.0;
  inversion_rate_     = 0.0;
}

MutationParams::MutationParams(const MutationParams & model)
{
  // --------------------------------------------------------- Mutation rates
  point_mutation_rate_  = model.point_mutation_rate_;
  small_insertion_rate_ = model.small_insertion_rate_;
  small_deletion_rate_  = model.small_deletion_rate_;
  max_indel_size_       = model.max_indel_size_;

  // ------------------------------ Rearrangement rates (without alignements)
  duplication_rate_   = model.duplication_rate_;
  deletion_rate_      = model.deletion_rate_;
  translocation_rate_ = model.translocation_rate_;
  inversion_rate_     = model.inversion_rate_;
}

// =================================================================
//                             Destructors
// =================================================================
MutationParams::~MutationParams()
{
}

std::unique_ptr<MutationParams> MutationParams::make_from_checkpoint(std::ifstream& is, mxifstream& mxis) {
  auto obj = std::make_unique<MutationParams>();

  obj->load_from_checkpoint(is, mxis);

  return obj;
}

// =================================================================
//                            Public Methods
// =================================================================
void MutationParams::write_to_checkpoint(std::ofstream& os, mxofstream&) const {
  // Mutation rates
  os << "PointMutationRate: " << point_mutation_rate_ << '\n';
  os << "SmallInsertionRate: " << small_insertion_rate_ << '\n';
  os << "SmallDeletionRate: " << small_deletion_rate_ << '\n';
  os << "MaxIndelSize: " << max_indel_size_ << '\n';

  // ------------------------------ Rearrangement rates (without alignements)
  os << "DuplicationRate: " << duplication_rate_ << '\n';
  os << "DeletionRate: " << deletion_rate_ << '\n';
  os << "TranslocationRate: " << translocation_rate_ << '\n';
  os << "InversionRate: " << inversion_rate_ << '\n';
}

void MutationParams::load_from_checkpoint(std::ifstream& is, mxifstream&) {
  std::string str;

  // Read local mutations parameters
  get_expected_or_throw(is, "PointMutationRate:", point_mutation_rate_);
  get_expected_or_throw(is, "SmallInsertionRate:", small_insertion_rate_);
  get_expected_or_throw(is, "SmallDeletionRate:", small_deletion_rate_);
  get_expected_or_throw(is, "MaxIndelSize:", max_indel_size_);

  // Read rearrangement parameters
  get_expected_or_throw(is, "DuplicationRate:", duplication_rate_);
  get_expected_or_throw(is, "DeletionRate:", deletion_rate_);
  get_expected_or_throw(is, "TranslocationRate:", translocation_rate_);
  get_expected_or_throw(is, "InversionRate:", inversion_rate_);
}

std::ostream& operator<<(std::ostream& os, const MutationParams& obj) {
  // Mutation rates
  os << "PointMutationRate: " << obj.point_mutation_rate() << '\n';
  os << "SmallInsertionRate: " << obj.small_insertion_rate() << '\n';
  os << "SmallDeletionRate: " << obj.small_deletion_rate() << '\n';
  os << "MaxIndelSize: " << obj.max_indel_size() << '\n';

  // ------------------------------ Rearrangement rates (without alignements)
  os << "DuplicationRate: " << obj.duplication_rate() << '\n';
  os << "DeletionRate: " << obj.deletion_rate() << '\n';
  os << "TranslocationRate: " << obj.translocation_rate() << '\n';
  os << "InversionRate: " << obj.inversion_rate() << '\n';

  return os;
}

// =================================================================
//                           Protected Methods
// =================================================================

// =================================================================
//                          Non inline accessors
// =================================================================
} // namespace aevol
