/*
 * CoverGTest.cpp
 *
 *  Created on: 12.12.2013
 *      Author: Maximilian Vogel (uocvf@student.kit.edu)
 */

#include <gtest/gtest.h>

#include <networkit/auxiliary/Log.hpp>
#include <networkit/structures/Cover.hpp>

#include <iostream>

namespace NetworKit {

class CoverGTest: public testing::Test {};

TEST_F(CoverGTest, testConstructor) {
    Cover c(10);
    EXPECT_EQ(0u, c.lowerBound());
    EXPECT_EQ(1u, c.upperBound());
}

TEST_F(CoverGTest, testAllToSingletonsAndUpperBound) {
    Cover c(10);
    EXPECT_EQ(1u, c.upperBound());
    c.allToSingletons();
    EXPECT_EQ(0u, c.lowerBound());
    EXPECT_EQ(11u, c.upperBound());
}

TEST_F(CoverGTest, testContains) {
    Cover c(10);
    c.toSingleton(0);
    EXPECT_TRUE(c.contains(0));
    EXPECT_FALSE(c.contains(1));
}

TEST_F(CoverGTest, testUpperBoundAfterMerges) {
    count n = 10;
    Cover c(n);
    for (index i = 0; i < n; i+=2) {
        index sid = c.toSingleton(i);
        c.toSingleton(i+1);
        c.addToSubset(sid,i+1);
    }
    for (index i = 0; i < n; i++) {
        c.addToSubset(i+1,0);
    }
    c.mergeSubsets(1,3);
    c.mergeSubsets(5,11);
    EXPECT_EQ(13u, c.upperBound());
}


TEST_F(CoverGTest, testToSingleton) {
    count n = 10;
    Cover c(n);
    c.allToSingletons();
    std::set<index> controlSet2;
    controlSet2.insert(1);
    DEBUG("c[0] ", c[0], " and controlSet2 ", controlSet2);
    EXPECT_TRUE(c[0] == controlSet2);
    c.addToSubset(5,0);
    c.addToSubset(2,0);
    c.addToSubset(3,0);
    c.addToSubset(4,0);
    c.addToSubset(0,1);
    c.toSingleton(0);
    std::set<index> controlSet;
    controlSet.insert(11);
    DEBUG("c[0] ", c[0], " and controlSet ", controlSet);
    EXPECT_TRUE(c[0] == controlSet);
}

TEST_F(CoverGTest, testAddToSubset) {
    count n = 10;
    Cover c(n);
    c.addToSubset(0,0);
    c.addToSubset(0,1);
    std::set<index> controlSet = {0};
    EXPECT_TRUE(c.inSameSubset(0,1));
    EXPECT_TRUE(c[0] == controlSet);
    EXPECT_TRUE(c[1] == controlSet);
}


TEST_F(CoverGTest, testAddToSubset2) {
    count n = 10;
    Cover c(n);
    index sid = c.toSingleton(0);
    c.addToSubset(sid,5);
    EXPECT_TRUE(c.inSameSubset(0,5));
}

TEST_F(CoverGTest, testMoveToSubset) {
    count n = 10;
    Cover c(n);
    c.allToSingletons();
    c.addToSubset(5,0);
    c.addToSubset(2,0);
    c.addToSubset(3,0);
    c.addToSubset(4,0);
    c.addToSubset(0,1);
    c.moveToSubset(8,0);
    std::set<index> controlSet = {8};
    EXPECT_EQ(c[0],controlSet);
}

TEST_F(CoverGTest, testSubsetSizesWithUnassignedElements) {
    count n = 10;
    Cover c(n);
    for (index i = 0; i < n; i+=2) {
        c.toSingleton(i);
    }
    std::vector<index> controlSet = {1,1,1,1,1};
    EXPECT_EQ(c.subsetSizes(),controlSet);
}

TEST_F(CoverGTest, testSubsetSizesTrivial) {
    count n = 10;
    Cover c(n);
    for (index i = 0; i < n; i++) {
        c.toSingleton(i);
    }
    std::vector<index> controlSet = {1,1,1,1,1,1,1,1,1,1};
    EXPECT_EQ(c.subsetSizes(),controlSet);
}

TEST_F(CoverGTest, testSubsetSizesTrivial2) {
    count n = 10;
    Cover c(n);
    for (index i = 0; i < n; i+=2) {
        c.toSingleton(i);
    }
    for (index i = 1; i < n; i+=2) {
        c.addToSubset((i/2)+1,i);
    }
    std::vector<index> controlSet = {2,2,2,2,2};
    EXPECT_EQ(c.subsetSizes(),controlSet);
}

TEST_F(CoverGTest, testSubsetSizesAssignedToMultipleSubsets) {
    count n = 10;
    Cover c(n);
    for (index i = 0; i < n; i++) {
        c.toSingleton(i);
    }
    for (index i = 1; i < n; i+=2) {
        c.addToSubset(i,i);
    }
    std::vector<index> controlSet = {2,1,2,1,2,1,2,1,2,1};
    EXPECT_EQ(c.subsetSizes(),controlSet);
}

TEST_F(CoverGTest, testSubsetSizesAssignedToMultipleSubsets2) {
    count n = 10;
    Cover c(n);
    for (index i = 0; i < n; i+=2) {
        index sid = c.toSingleton(i);
        c.toSingleton(i+1);
        c.addToSubset(sid,i+1);
    }
    for (index i = 0; i < n; i++) {
        c.addToSubset(i+1,0);
    }
    std::vector<index> controlSet = {2,2,3,2,3,2,3,2,3,2};
    EXPECT_EQ(c.subsetSizes(),controlSet);
}

TEST_F(CoverGTest, testSubsetSizeMapMultipleSets) {
    count n = 10;
    Cover c(n);
    for (index i = 0; i < n; i++) {
        c.toSingleton(i);
    }
    for (index i = 1; i < n; i+=2) {
        c.addToSubset(i,i);
    }
    std::map<index,count> controlMap;
    controlMap[1] = 2;
    controlMap[2] = 1;
    controlMap[3] = 2;
    controlMap[4] = 1;
    controlMap[5] = 2;
    controlMap[6] = 1;
    controlMap[7] = 2;
    controlMap[8] = 1;
    controlMap[9] = 2;
    controlMap[10] = 1;
    EXPECT_EQ(c.subsetSizeMap(),controlMap);
}

TEST_F(CoverGTest, testMergeSubsetsAndGetMembers) {
    count n = 10;
    Cover c(n);
    for (index i = 0; i < n; i+=2) {
        index sid = c.toSingleton(i);
        c.toSingleton(i+1);
        c.addToSubset(sid,i+1);
    }
    for (index i = 0; i < n; i++) {
        c.addToSubset(i+1,0);
    }
    c.mergeSubsets(1,3);
    c.mergeSubsets(5,11);
    auto c11 = c.getMembers(11);
    std::vector<index> controlSetSizes = {2,2,2,3,2,3,2,6};
    // remaining subset IDs 2,4,6,7,8,9,10,12
    // their sizes          2,2,2,3,2,3,2,6
    std::set<index> controlSetMembers = {0,1,2,3,4,5};
    EXPECT_EQ(controlSetSizes,c.subsetSizes()); // check if subsets sizes are correct
    auto c12 = c.getMembers(12);
    EXPECT_EQ(c12,controlSetMembers); // check if elements of merged subsets are correct
}

TEST_F(CoverGTest, testNumberOfSubsets) {
    count n = 10;
    Cover c(n);
    for (index i = 0; i < n; i+=2) {
        index sid = c.toSingleton(i);
        c.toSingleton(i+1);
        c.addToSubset(sid,i+1);
    }
    for (index i = 0; i < n; i++) {
        c.addToSubset(i+1,0);
    }
    EXPECT_EQ(n,c.numberOfSubsets());
    c.mergeSubsets(1,2);
    c.mergeSubsets(3,11);
    EXPECT_EQ(8u, c.numberOfSubsets());
}


TEST_F(CoverGTest, testSubsetsOf) {
    count n = 10;
    Cover c(n);
    for (index i = 0; i < n; i+=2) {
        index sid = c.toSingleton(i);
        c.toSingleton(i+1);
        c.addToSubset(sid,i+1);
    }
    for (index i = 0; i < n; i++) {
        c.addToSubset(i+1,0);
    }
    auto subsetsOf0 = c.subsetsOf(0);
    std::set<index> controlSet0 = {1,2,3,4,5,6,7,8,9,10};
    auto subsetsOf3 = c.subsetsOf(3);
    std::set<index> controlSet3 = {3,4};
    EXPECT_EQ(controlSet0,subsetsOf0);
    EXPECT_EQ(controlSet3,subsetsOf3);
    c.mergeSubsets(1,3);
    c.mergeSubsets(5,11);
    subsetsOf0 = c.subsetsOf(0);
    controlSet0 = {2,4,6,7,8,9,10,12};
    EXPECT_EQ(controlSet0,subsetsOf0);
}

TEST_F(CoverGTest, testInSameSubset) {
    count n = 10;
    Cover c(n);
    for (index i = 0; i < n; i+=2) {
        index sid = c.toSingleton(i);
        c.toSingleton(i+1);
        c.addToSubset(sid,i+1);
    }
    EXPECT_TRUE(c.inSameSubset(0,1));
    EXPECT_FALSE(c.inSameSubset(0,2));
    EXPECT_FALSE(c.inSameSubset(1,5));
    c.mergeSubsets(1,3);
    EXPECT_TRUE(c.inSameSubset(0,1));
    EXPECT_TRUE(c.inSameSubset(0,2));
    EXPECT_FALSE(c.inSameSubset(1,5));
    c.mergeSubsets(5,11);
    EXPECT_TRUE(c.inSameSubset(0,1));
    EXPECT_TRUE(c.inSameSubset(0,2));
    EXPECT_TRUE(c.inSameSubset(1,5));
}


} /* namespace NetworKit */
