// Copyright (C) 2018  INRIA
//
// Treerecs is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// Treerecs 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

#include "gtest/gtest.h"
#include "examples_paths.h"
#include <treerecs/tools/utils.h>
#include <treerecs/tools/IO/PhyloXML.h>
#include <treerecs/tools/IO/XMLUtils.h>
#include <treerecs/tools/IO/IO.h>
using namespace treerecs;

class PhyloXML_tests: public testing::Test {
public:
 std::string fileexample = phyloxml_path + "phyloxml_example_complete.txt";

 PhyloXML phyloxml;
};

TEST_F(PhyloXML_tests, XMLUtils_test) {

  //first test
  std::string tag_start = "<This_is_a_tag a=\"0\"  b=\"1\">";
  XMLTag tag_start_xml = XMLUtils::readXMLTag(tag_start);
  ASSERT_EQ(tag_start_xml.type, XMLTagType::start);
  ASSERT_TRUE(utils::string_comp(tag_start_xml.name, "This_is_a_tag"));
  ASSERT_TRUE(utils::string_comp(tag_start_xml.attributes.at("a"), "0"));
  ASSERT_TRUE(utils::string_comp(tag_start_xml.attributes.at("b"), "1"));

  std::string tag_end = "</This_is_a_tag>";
  XMLTag tag_end_xml = XMLUtils::readXMLTag(tag_end);
  ASSERT_EQ(tag_end_xml.type, XMLTagType::end);
  ASSERT_TRUE(utils::string_comp(tag_end_xml.name, "This_is_a_tag"));
}

TEST_F(PhyloXML_tests, PhyloXML_test) {

  // First try: with PhyloXML class.
  // std::cout << "Reading trees in " << phyloxml.getFormatName()
  //           << " format." << std::endl;
  // std::cout << phyloxml.getFormatDescription() << std::endl;

  std::vector<bpp::PhyloTree *> trees;
  phyloxml.read(fileexample, trees);

  ASSERT_STREQ("((A:0.102,B:0.23):0.06,C:0.4);\n",
               IO::PhyloTreeToNewick(*trees[0]).c_str());
  ASSERT_STREQ("((A:0.102,B:0.23):0.06,C:0.4);\n",
               IO::PhyloTreeToNewick(*trees[1]).c_str());
  ASSERT_STREQ("((A:0.102,B:0.23)89:0.06,C:0.4);\n",
               IO::PhyloTreeToNewick(*trees[2]).c_str());
  ASSERT_STREQ("((A,B),C);\n", IO::PhyloTreeToNewick(*trees[3]).c_str());
  ASSERT_STREQ("((0,1),3);\n", IO::PhyloTreeToNewick(*trees[4]).c_str());
  ASSERT_STREQ("((0,1),3);\n", IO::PhyloTreeToNewick(*trees[5]).c_str());
  ASSERT_STREQ("((A:0.102,B:0.23):0.06,C:0.4);\n",
               IO::PhyloTreeToNewick(*trees[6]).c_str());
  ASSERT_STREQ("((A,B),C);\n", IO::PhyloTreeToNewick(*trees[7]).c_str());
  ASSERT_STREQ("((A,B),C);\n", IO::PhyloTreeToNewick(*trees[8]).c_str());
  ASSERT_STREQ("(0,(1,2));\n", IO::PhyloTreeToNewick(*trees[9]).c_str());
  ASSERT_STREQ("((A,B,C),D);\n", IO::PhyloTreeToNewick(*trees[10]).c_str());
  ASSERT_STREQ("((A,B),C);\n", IO::PhyloTreeToNewick(*trees[11]).c_str());
  ASSERT_STREQ("((A,B),C);\n", IO::PhyloTreeToNewick(*trees[12]).c_str());

  for (auto tree: trees) {
    delete tree;
  }
}

TEST_F(PhyloXML_tests, IO_test) {

  auto trees = IO::readTreesFile(fileexample, TextFormat::phyloxml,
                                 -1, true, false);

  ASSERT_EQ(trees.size(), 13);

  ASSERT_STREQ("((A:0.102,B:0.23):0.06,C:0.4);\n",
               IO::PhyloTreeToNewick(*trees[0]).c_str());
  ASSERT_STREQ("((A:0.102,B:0.23):0.06,C:0.4);\n",
               IO::PhyloTreeToNewick(*trees[1]).c_str());
  ASSERT_STREQ("((A:0.102,B:0.23)89:0.06,C:0.4);\n",
               IO::PhyloTreeToNewick(*trees[2]).c_str());
  ASSERT_STREQ("((A,B),C);\n", IO::PhyloTreeToNewick(*trees[3]).c_str());
  ASSERT_STREQ("((0,1),3);\n", IO::PhyloTreeToNewick(*trees[4]).c_str());
  ASSERT_STREQ("((0,1),3);\n", IO::PhyloTreeToNewick(*trees[5]).c_str());
  ASSERT_STREQ("((A:0.102,B:0.23):0.06,C:0.4);\n",
               IO::PhyloTreeToNewick(*trees[6]).c_str());
  ASSERT_STREQ("((A,B),C);\n", IO::PhyloTreeToNewick(*trees[7]).c_str());
  ASSERT_STREQ("((A,B),C);\n", IO::PhyloTreeToNewick(*trees[8]).c_str());
  ASSERT_STREQ("(0,(1,2));\n", IO::PhyloTreeToNewick(*trees[9]).c_str());
  ASSERT_STREQ("((A,B,C),D);\n", IO::PhyloTreeToNewick(*trees[10]).c_str());
  ASSERT_STREQ("((A,B),C);\n", IO::PhyloTreeToNewick(*trees[11]).c_str());
  ASSERT_STREQ("((A,B),C);\n", IO::PhyloTreeToNewick(*trees[12]).c_str());
}
