#include <gtest/gtest.h>

#include <fstream>
#include <string>

#include "io/fasta/fasta.h"
#include "macros.h"

using namespace aevol;

TEST(FastaTest, SimpleFasta) {
  auto file_name = std::string("./simple_fasta.fa");
  auto genome = std::string("GATTACA");
  auto binary_genome = genome;
  std::transform(genome.cbegin(), genome.cend(), binary_genome.begin(), atcg_to_num);

  std::ofstream out_file(file_name);
  out_file << ">seq_42 [organism=aevol]\n" << genome << "\n";
  out_file.close();

  std::ifstream fasta_file(file_name);
  auto [seqid, sequence, modifiers] = read_fasta_sequence(fasta_file, file_name);
  EXPECT_STREQ(seqid.c_str(), "seq_42");
  EXPECT_STREQ(sequence.c_str(), binary_genome.c_str());
  EXPECT_EQ(modifiers.size(), 1);
  EXPECT_STREQ(modifiers.at("organism").c_str(), "aevol");
}

TEST(FastaTest, FastaWithModifiers) {
  auto file_name = std::string("./fasta_with_modifiers.fa");
  auto genome = std::string("GATTACA");
  auto binary_genome = genome;
  std::transform(genome.cbegin(), genome.cend(), binary_genome.begin(), atcg_to_num);

  std::ofstream out_file(file_name);
  out_file << ">seq_with_mods [organism=aevol] [mod1=value1] [mod2=123]\n" << genome << "\n";
  out_file.close();

  std::ifstream fasta_file(file_name);
  auto [seqid, sequence, modifiers] = read_fasta_sequence(fasta_file, file_name);
  EXPECT_STREQ(seqid.c_str(), "seq_with_mods");
  EXPECT_STREQ(sequence.c_str(), binary_genome.c_str());
  // Check modifiers
  EXPECT_EQ(modifiers.size(), 3);
  EXPECT_STREQ(modifiers.at("organism").c_str(), "aevol");
  EXPECT_STREQ(modifiers.at("mod1").c_str(), "value1");
  EXPECT_STREQ(modifiers.at("mod2").c_str(), "123");
}

TEST(FastaTest, NonAevolFasta) {
  auto file_name = std::string("./non_aevol_fasta.fa");
  std::ofstream out_file(file_name);
  out_file << ">seq_42\n" << "GATTACA\n";
  out_file.close();

  std::ifstream fasta_file(file_name);
  EXPECT_THROW(read_fasta_sequence(fasta_file, file_name), non_aevol_fasta_error);
}

TEST(FastaTest, NonValidFasta) {
  auto file_name = std::string("./non_valid_fasta.fa");
  std::ofstream out_file(file_name);
  out_file << "seq_42\n" << "GATTACA\n";
  out_file.close();

  std::ifstream fasta_file(file_name);
  EXPECT_THROW(read_fasta_sequence(fasta_file, file_name), fasta_error);
}
