// ****************************************************************************
//
//          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 "FastaReader.h"

#include <charconv>

namespace aevol {

FastaReader::FastaReader(std::filesystem::path filename): filename_(filename), in_(filename) {
  if (not in_) {
    throw std::runtime_error(std::string("failed to open file ") + filename_.string());
  }

  // Set stream to trigger an exception on EOF
  in_.exceptions(std::ifstream::eofbit);
}

auto FastaReader::read_individual() -> fasta_structured_individual_t {
  if (not exp_setup->diploid()) {
    auto [seqid, sequence, modifiers] = read_sequence();
    return {seqid, Individual::make_from_sequence(sequence), modifiers};
  } else {
    auto [seqid_chrsmA, sequence_chrsmA, modifiers_chrsmA] = read_sequence();
    auto [seqid_chrsmB, sequence_chrsmB, modifiers_chrsmB] = read_sequence();
    // Define seqid as seqid_chrsmA stripped of any Chrsm suffix
    std::smatch chrsm_suffix_match;
    std::regex_search(seqid_chrsmA, chrsm_suffix_match, std::regex(R"((-Chrsm::[AB]))"));
    auto seqid = chrsm_suffix_match.empty() ? seqid_chrsmA : std::string(chrsm_suffix_match.prefix());
    return {seqid, Individual::make_from_sequences(sequence_chrsmA, sequence_chrsmB), modifiers_chrsmA};
  }
}

auto FastaReader::seqid_to_generation(std::string seqid) const -> time_type {
  std::smatch m;
  std::regex_search(seqid, m, std::regex(R"(Seq(\w+)-)"));
  auto generation = aevol::time_type{};
  if (m.size() == 0) {
    aevol::exit_with_usr_msg(
        std::format("could not infer generation from SeqID {} in file {}\n", seqid, filename_.string()));
  } else {
    auto m_str = m[1].str();
    std::from_chars(m_str.data(), m_str.data() + m_str.size(), generation);
  }
  return generation;
}

}  // namespace aevol
