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

#ifndef AEVOL_ALIGNMENTPARAMS_H
#define AEVOL_ALIGNMENTPARAMS_H

#include <cstdint>
#include <fstream>
#include <functional>

#include "Alignment.h"
#include "ScoreFunction.h"

#include "checkpointing/mxifstream.h"
#include "checkpointing/mxofstream.h"

namespace aevol {

namespace align {

class AlignmentParams {
 public:
  AlignmentParams()                                  = default;
  AlignmentParams(const AlignmentParams&)            = delete;
  AlignmentParams(AlignmentParams&&)                 = default;
  AlignmentParams& operator=(const AlignmentParams&) = delete;
  AlignmentParams& operator=(AlignmentParams&&)      = default;
  virtual ~AlignmentParams()                         = default;

  static auto make_from_checkpoint(std::ifstream& is, mxifstream& mxis) -> std::unique_ptr<AlignmentParams>;
  static auto make_from_params(int8_t match_bonus,
                               int8_t mismatch_cost,
                               ScoreFunction& score_function,
                               double neighbourhood_rate,
                               Dna::size_type max_align_size) -> std::unique_ptr<AlignmentParams>;

  void write_to_checkpoint(std::ofstream& os, mxofstream& mxos) const;

  auto generate_target_score(JumpingMT& prng) const { return (*score_function_)(prng); }

  auto match_bonus() const { return match_bonus_; }
  auto mismatch_cost() const { return mismatch_cost_; }
  auto neighbourhood_rate() const { return neighbourhood_rate_; }
  auto max_align_size() const { return max_align_size_; }

 protected:
  int16_t match_bonus_                           = 1;   // Score bonus for matching residues
  int16_t mismatch_cost_                         = -2;  // Score cost for mismatched residues
  std::unique_ptr<ScoreFunction> score_function_ = nullptr;
  double neighbourhood_rate_                     = 2.0;
  Dna::size_type max_align_size_                 = 150;  // Size at which we should stop evaluating an alignment

  void load_from_checkpoint(std::ifstream& is, mxifstream& mxis);
};

}  // namespace align

}  // namespace aevol

#endif  // AEVOL_ALIGNMENTPARAMS_H
