#include "llvm/Support/SuffixTree.h"
#include "gtest/gtest.h"
#include <vector>
using namespace llvm;
namespace {
TEST(SuffixTreeTest, TestSingleRepetition) {
  std::vector<unsigned> SimpleRepetitionData = {1, 2, 1, 2, 3};
  SuffixTree ST(SimpleRepetitionData);
  std::vector<SuffixTree::RepeatedSubstring> SubStrings;
  for (auto It = ST.begin(); It != ST.end(); It++)
    SubStrings.push_back(*It);
  ASSERT_EQ(SubStrings.size(), 1u);
  EXPECT_EQ(SubStrings[0].Length, 2u);
  EXPECT_EQ(SubStrings[0].StartIndices.size(), 2u);
  for (unsigned StartIdx : SubStrings[0].StartIndices) {
    EXPECT_EQ(SimpleRepetitionData[StartIdx], 1u);
    EXPECT_EQ(SimpleRepetitionData[StartIdx + 1], 2u);
  }
}
TEST(SuffixTreeTest, TestLongerRepetition) {
  std::vector<unsigned> RepeatedRepetitionData = {1, 2, 3, 1, 2, 3, 4};
  SuffixTree ST(RepeatedRepetitionData);
  std::vector<SuffixTree::RepeatedSubstring> SubStrings;
  for (auto It = ST.begin(); It != ST.end(); It++)
    SubStrings.push_back(*It);
  EXPECT_EQ(SubStrings.size(), 2u);
  unsigned Len;
  for (SuffixTree::RepeatedSubstring &RS : SubStrings) {
    Len = RS.Length;
    bool IsExpectedLen = (Len == 3u || Len == 2u);
    bool IsExpectedIndex;
    ASSERT_TRUE(IsExpectedLen);
    if (Len == 3u) {
      for (unsigned StartIdx : RS.StartIndices) {
        IsExpectedIndex = (StartIdx == 0u || StartIdx == 3u);
        EXPECT_TRUE(IsExpectedIndex);
        EXPECT_EQ(RepeatedRepetitionData[StartIdx], 1u);
        EXPECT_EQ(RepeatedRepetitionData[StartIdx + 1], 2u);
        EXPECT_EQ(RepeatedRepetitionData[StartIdx + 2], 3u);
      }
    } else {
      for (unsigned StartIdx : RS.StartIndices) {
        IsExpectedIndex = (StartIdx == 1u || StartIdx == 4u);
        EXPECT_TRUE(IsExpectedIndex);
        EXPECT_EQ(RepeatedRepetitionData[StartIdx], 2u);
        EXPECT_EQ(RepeatedRepetitionData[StartIdx + 1], 3u);
      }
    }
  }
}
TEST(SuffixTreeTest, TestSingleCharacterRepeat) {
  std::vector<unsigned> RepeatedRepetitionData = {1, 1, 1, 1, 1, 1, 2};
  std::vector<unsigned>::iterator RRDIt, RRDIt2;
  SuffixTree ST(RepeatedRepetitionData);
  std::vector<SuffixTree::RepeatedSubstring> SubStrings;
  for (auto It = ST.begin(); It != ST.end(); It++)
    SubStrings.push_back(*It);
  EXPECT_EQ(SubStrings.size(), 1u);
  for (SuffixTree::RepeatedSubstring &RS : SubStrings) {
    EXPECT_EQ(RS.StartIndices.size(),
              RepeatedRepetitionData.size() - RS.Length);
    for (unsigned StartIdx : SubStrings[0].StartIndices) {
      RRDIt = RRDIt2 = RepeatedRepetitionData.begin();
      std::advance(RRDIt, StartIdx);
      std::advance(RRDIt2, StartIdx + SubStrings[0].Length);
      ASSERT_TRUE(
          all_of(make_range<std::vector<unsigned>::iterator>(RRDIt, RRDIt2),
                 [](unsigned Elt) { return Elt == 1; }));
    }
  }
}
TEST(SuffixTreeTest, TestTandemRepeat) {
  std::vector<unsigned> RepeatedRepetitionData = {1, 2, 3, 1, 2, 3};
  SuffixTree ST(RepeatedRepetitionData);
  std::vector<SuffixTree::RepeatedSubstring> SubStrings;
  for (auto It = ST.begin(); It != ST.end(); It++)
    SubStrings.push_back(*It);
  EXPECT_EQ(SubStrings.size(), 0u);
}
TEST(SuffixTreeTest, TestExclusion) {
  std::vector<unsigned> RepeatedRepetitionData = {1, 1, 2, 1, 1, 3};
  std::vector<unsigned>::iterator RRDIt, RRDIt2;
  SuffixTree ST(RepeatedRepetitionData);
  std::vector<SuffixTree::RepeatedSubstring> SubStrings;
  for (auto It = ST.begin(); It != ST.end(); It++)
    SubStrings.push_back(*It);
  EXPECT_EQ(SubStrings.size(), 1u);
  bool IsExpectedIndex;
  for (SuffixTree::RepeatedSubstring &RS : SubStrings) {
    for (unsigned StartIdx : RS.StartIndices) {
      IsExpectedIndex = (StartIdx == 0u || StartIdx == 3u);
      EXPECT_TRUE(IsExpectedIndex);
      RRDIt = RRDIt2 = RepeatedRepetitionData.begin();
      std::advance(RRDIt, StartIdx);
      std::advance(RRDIt2, StartIdx + RS.Length);
      EXPECT_TRUE(
          all_of(make_range<std::vector<unsigned>::iterator>(RRDIt, RRDIt2),
                 [](unsigned Elt) { return Elt == 1; }));
    }
  }
}
}