// Author: Lance Hepler

#include <string>

using std::string;

#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include <pacbio/ccs/SparseAlignment.h>

TEST(SparseAlignTest, ExactAlign)
{
    const size_t K = 5;
    string s1 = "ACGTACACACAGTACAGTACAAGTTTCACGGACATTTGGTTCCCACTTGTACAGTGCACACGGGTTACACGT";
    auto chain = PacBio::CCS::SparseAlign(K, s1, s1);
    auto fst = chain[0];
    auto lst = chain[chain.size() - 1];

    EXPECT_EQ(s1.size() - K + 1, chain.size());
    EXPECT_EQ(0, fst.first);
    EXPECT_EQ(0, fst.second);
    EXPECT_EQ(s1.size() - K, lst.first);
    EXPECT_EQ(s1.size() - K, lst.second);
}

TEST(SparseAlignTest, ExactPartial)
{
    const size_t K = 5;
    string s1 = "ACGTACACACAGTACAGTACAAGTTTCACGGACATTTGGTTCCCACTTGTACAGTGCACACGGGTTACACGT";
    string s2 = "TTTGGTTCCCACTTGTACAGTGCACACGGGTTACACGT";
    auto chain = PacBio::CCS::SparseAlign(K, s1, s2);
    auto fst = chain[0];
    auto lst = chain[chain.size() - 1];

    EXPECT_EQ(s2.size() - K + 1, chain.size());
    EXPECT_EQ(34, fst.first);
    EXPECT_EQ(0, fst.second);
    EXPECT_EQ(s1.size() - K, lst.first);
    EXPECT_EQ(s2.size() - K, lst.second);
}

TEST(SparseAlignTest, InsertAlign)
{
    const size_t K = 5;
    string s1 = "ACGTACACACAGTACAGTACAAGTTTCACGGACATTTGGTTCCCACTTGTACAGTGCACACGGGTTACACGT";
    string s2 =
        "ACGTACACACAGTACAGTACAAGTTTCACGGACATAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATTGGTTCCCACTTGTAC"
        "AGTGCACACGGGTTACACGT";
    auto chain = PacBio::CCS::SparseAlign(K, s1, s2);
    auto fst = chain[0];
    auto lst = chain[chain.size() - 1];

    EXPECT_EQ(0, fst.first);
    EXPECT_EQ(0, fst.second);
    EXPECT_EQ(s1.size() - K, lst.first);
    EXPECT_EQ(s2.size() - K, lst.second);
}

TEST(SparseAlignTest, NoAlign)
{
    const size_t K = 5;
    string s1 = "ACGTACACACAGTACAGTACAAGTTTCACGGACATTTGGTTCCCACTTGTACAGTGCACACGGGTTACACGT";
    string s2 = "AAAATCCCCCCCCCCAGGGGG";
    auto chain = PacBio::CCS::SparseAlign(K, s1, s2);

    EXPECT_EQ(0, chain.size());
}

TEST(SparseAlignTest, SimpleAlign)
{
    const size_t K = 5;
    string s1 = "ACGTACACACAGTACAGTACAAGTTTCACGGACATTTGGTTCCCACTTGTACAGTGCACACGGGTTACACGT";
    string s2 = "ACGTACACCAGTAAGTACAAGTTTCACGCGAATTTGGTTCCCACTTGTCAAGTGCACACGGGTTACACGT";
    auto chain = PacBio::CCS::SparseAlign(K, s1, s2);
    auto fst = chain[0];
    auto lst = chain[chain.size() - 1];

    EXPECT_EQ(0, fst.first);
    EXPECT_EQ(0, fst.second);
    EXPECT_EQ(s1.size() - K, lst.first);
    EXPECT_EQ(s2.size() - K, lst.second);
}

TEST(SparseAlignTest, LongAlign)
{
    const size_t K = 5;
    string s1 =
        "AGAGAACATCGCTATCCGCAGATAAAGCAAATCCTTCCAGACCAACAACCAATCGTAGCAAAAACATTCAGCGAACAGCAACACGCAGTT"
        "AGACCAACGAAAACTATGGGACAGCTAGATAGACACACAACATACAAAAAATATAACTCGCCCCATAGATCACAATAGAGCTGGATGCAG"
        "AAAGACTAGAAGAAGTGGGTGTATACGCAGCATTAAACAGCAGAGAGATAGTTCCTAACAAACAGACATATGGGTAATAAGACACAATCA"
        "ACAAAGCAAACATAAGAGCGAATATTGCAGGATAACTAATTAGAAGCTAATAAATACGAAACTACAGAGCAGTAAGACCAGATTAAATGA"
        "GAAATCGACGAACCGAGACTGGACTCATGGAAGTGGAAGAACAGATAAGAAAGACAAGAACATGAAAAAATCAGATATAAGATATATACT"
        "CCAGATGGACAGAACAATAACATAATGCACATACTAATACACACAGAGAGCGAATCAAGACGACTGAAATATATAACAAATATATACACA"
        "TTGTACACACAACAACAGGATATTCTGAGTACCAAAGCTCAACAGTATTGCAGGATAAAATACACAGAAGAGACACATATATACGGATAT"
        "ACAGGGAACCAGAAATACACGCGAATGACTGTTCTGGAAGCCATTTATAGACAGTAAGAATATGGCACCCAATACATACACGCACGTATA"
        "CTGACACACAAAGACAGATTACATCATACACACAATGACACATTTGGGCGAGAGATTACAACCACGTATGAATACAACAAGAGAAACCGA"
        "CGCAAACAACATAGATCAGATATTTAGCTGAAAAATGTACCAGAACTTTAGAAGAAAGGAAAATACACTACAAGCATAGGTGAGAAGCAC"
        "AACCATTCGATTATGCAACAGAATCTACAGATACTATAT";
    string s2 =
        "AGAGAACAATCGCTATCCGCAAGATAAAGCAAATCCTTCCAGACCAACAACCAATCAGTAGCAAAAACATTCAGCGAACAGCAAACACGC"
        "AGTTAGACCAGACGAAAACTATGGGACTAAGCTAGATAGACACACAACATACAAAAAATATAAGACAGTCGAGCCAGCCATAAGAGAGAG"
        "AGTGTGAGAGTATATCACAATAGAGCTGGATGCAGAAAGACTAAGAAGAAGTGGGTGTATACGCAGCATTAAAAGCAGAGAGATGTTCCT"
        "AACAAACAGACATATGGGTAATAAGACAATCAACAAAGCAAACATAAGAGCGAAATATTGCAGGAGTTAACTAATTAGAAGCTAAATAAA"
        "TACGAAACTACAGAGCAGTAAGACCAGATTAAATTCATGGAAGTGGAAGAACAGATAAGAAAGACAAAGAACATGAAAAAATCAGATATA"
        "AGATATAGATACTCCAGATGGACAGAACAATAACAAGTAATGCACATACTAATACACACAGAGAGCGAATCAAGACGACTGAAATATATA"
        "ACAAATATATACACATTGTACACACAACAACAGGATATTCTGAGTACCAAAGCTCAACAGTATTGCAGGATAAAATACACAGAAGAGACA"
        "CATATATACGGATATACAGGGAACCAGAAATACACGCGAATGACTGTTCTGGAAGCCATTTATAGACAGTAAGAATATGGCACCCAATAC"
        "ATACACGCACGTATACTGACACACAAAGACAGATTACATCATACACACAATGACACATTTGGGCGAGAGATTACAACCACGTATGAATAC"
        "AACAAGAGAAACCGACGCAAACAACATAGATCAGATATTTAGCTGAAAAATGTACCAGAACTTTAGAAGAAAGGAAAATACACGTACAAG"
        "CATAGGTGAGAAGCACAACCATTCGATTATGCAACAGAATCTACAGATACTATAT";
    auto chain = PacBio::CCS::SparseAlign(K, s1, s2);
    auto fst = chain[0];
    auto lst = chain[chain.size() - 1];

    EXPECT_EQ(0, fst.first);
    EXPECT_EQ(0, fst.second);
    EXPECT_GT(lst.first, 900);
    EXPECT_GT(lst.second, 900);
}
