#include <algorithm>
#include <cassert>
#include <iostream>
#include <vector>

#include "support/small_set.h"

using namespace wasm;

template<typename T>
void assertContents(T& t, const std::vector<int>& expectedContents) {
  assert(t.size() == expectedContents.size());
  for (auto item : expectedContents) {
    assert(t.contains(item));
  }
  // Also test this using an iterator and a const iterator to also get
  // coverage there.
  for (auto& item : t) {
    assert(std::find(expectedContents.begin(), expectedContents.end(), item) !=
           expectedContents.end());
  }
  for (const auto& item : t) {
    assert(std::find(expectedContents.begin(), expectedContents.end(), item) !=
           expectedContents.end());
  }
}

template<typename T> void testAPI() {
  {
    T t;

    // build up with no duplicates
    assert(t.empty());
    assert(t.size() == 0);
    t.insert(1);
    assertContents(t, {1});
    assert(!t.empty());
    assert(t.size() == 1);
    t.insert(2);
    assertContents(t, {1, 2});
    assert(!t.empty());
    assert(t.size() == 2);
    t.insert(3);
    assertContents(t, {1, 2, 3});
    assert(!t.empty());

    // unwind
    assert(t.size() == 3);
    t.erase(3);
    assertContents(t, {1, 2});
    assert(t.size() == 2);
    t.erase(2);
    assertContents(t, {1});
    assert(t.size() == 1);
    t.erase(1);
    assertContents(t, {});
    assert(t.size() == 0);
    assert(t.empty());
  }
  {
    T t;

    // build up with duplicates
    t.insert(1);
    t.insert(2);
    t.insert(2);
    t.insert(3);
    assertContents(t, {1, 2, 3});
    assert(t.size() == 3);

    // unwind by erasing (in the opposite direction from before)
    assert(t.contains(1));
    assert(t.contains(2));
    assert(t.contains(3));
    assert(!t.contains(1337));

    t.erase(1);
    assert(!t.contains(1));

    assert(t.size() == 2);

    assert(t.contains(2));
    t.erase(2);
    assert(!t.contains(2));

    assert(t.size() == 1);

    assert(t.contains(3));
    t.erase(3);

    assert(!t.contains(1));
    assert(!t.contains(2));
    assert(!t.contains(3));
    assert(!t.contains(1337));

    assert(t.size() == 0);
  }
  {
    T t;

    // build up
    t.insert(1);
    t.insert(2);
    t.insert(3);

    // unwind by clearing
    t.clear();
    assert(t.size() == 0);
    assert(t.empty());
  }
  {
    T t, u;
    // comparisons
    assert(t == u);
    t.insert(1);
    assert(t != u);
    u.insert(1);
    assert(t == u);
    u.erase(1);
    assert(t != u);
    u.insert(2);
    assert(t != u);
  }
  {
    T t, u;
    // comparisons should ignore the order of insertion
    t.insert(1);
    t.insert(2);
    u.insert(2);
    u.insert(1);
    assert(t == u);
  }
  {
    T t, u;
    // comparisons should ignore the mode: in a SmallSet<1>, a set of size 1
    // can be either fixed - if we just grew it to size 1 - or flexible - if we
    // grew it enough to be flexible, then shrank it back (as it only becomes
    // fixed at size 0).
    t.insert(1);

    u.insert(1);
    u.insert(2);

    // one extra item in u
    assert(t != u);
    assert(u != t);

    // remove the extra item
    u.erase(2);

    assert(t == u);
    assert(u == t);
  }
  {
    T t, u;
    // as above, but for size 2, and don't erase the last item added
    t.insert(1);
    t.insert(2);

    u.insert(3);
    u.insert(2);
    u.insert(1);

    // one extra item in u
    assert(t != u);
    assert(u != t);

    // remove the extra item
    u.erase(3);

    assert(t == u);
    assert(u == t);
  }
}

template<typename T> void testInternals() {
  {
    T s;
    // Start out using fixed storage.
    assert(s.TEST_ONLY_NEVER_USE_usingFixed());
    // Adding one item still keeps us using fixed storage, as that is the exact
    // amount we have in fact.
    s.insert(0);
    assert(s.TEST_ONLY_NEVER_USE_usingFixed());
    // Adding one more item forces us to use flexible storage.
    s.insert(1);
    assert(!s.TEST_ONLY_NEVER_USE_usingFixed());
    // Removing an item returns us to size 1, *but we keep using flexible
    // storage*. We do not ping-pong between flexible and fixed; once flexible,
    // we stay that way.
    s.erase(0);
    assert(!s.TEST_ONLY_NEVER_USE_usingFixed());
    // However, removing all items does return us to using fixed storage, should
    // we ever insert again.
    s.erase(1);
    assert(s.empty());
    assert(s.TEST_ONLY_NEVER_USE_usingFixed());
    // And once more we can add an additional item while remaining fixed.
    s.insert(10);
    assert(s.TEST_ONLY_NEVER_USE_usingFixed());
  }
}

// Iterate over an input object and check we have the same items, in the same
// order, as we expect.
template<typename T>
void assertEqualOrdered(const T& t, const std::vector<int>& expected) {
  size_t index = 0;
  for (auto x : t) {
    assert(index < expected.size());
    assert(x == expected[index]);
    index++;
  }
}

template<typename T> void testOrdering() {
  T t;

  // Do some inserts at the end.
  t.insert(1);
  assertEqualOrdered(t, {1});

  t.insert(2);
  assertEqualOrdered(t, {1, 2});

  t.insert(3);
  assertEqualOrdered(t, {1, 2, 3});

  // Erase the start.
  t.erase(1);
  assertEqualOrdered(t, {2, 3});

  // Insert at the start.
  t.insert(1);
  assertEqualOrdered(t, {1, 2, 3});

  // Erase the end.
  t.erase(3);
  assertEqualOrdered(t, {1, 2});

  // Erase the end.
  t.erase(2);
  assertEqualOrdered(t, {1});

  // Insert at the end.
  t.insert(3);
  assertEqualOrdered(t, {1, 3});

  // Insert at the middle.
  t.insert(2);
  assertEqualOrdered(t, {1, 2, 3});

  // Erase the middle.
  t.erase(2);
  assertEqualOrdered(t, {1, 3});
}

int main() {
  testAPI<SmallSet<int, 0>>();
  testAPI<SmallSet<int, 1>>();
  testAPI<SmallSet<int, 2>>();
  testAPI<SmallSet<int, 3>>();
  testAPI<SmallSet<int, 10>>();

  testAPI<SmallUnorderedSet<int, 0>>();
  testAPI<SmallUnorderedSet<int, 1>>();
  testAPI<SmallUnorderedSet<int, 2>>();
  testAPI<SmallUnorderedSet<int, 3>>();
  testAPI<SmallUnorderedSet<int, 10>>();

  testInternals<SmallSet<int, 1>>();
  testInternals<SmallUnorderedSet<int, 1>>();

  testOrdering<SmallSet<int, 0>>();
  testOrdering<SmallSet<int, 1>>();
  testOrdering<SmallSet<int, 2>>();
  testOrdering<SmallSet<int, 3>>();
  testOrdering<SmallSet<int, 10>>();

  std::cout << "ok.\n";
}
