#include "tests/StringBufferTests.h"
#include "tests/Test.h"
#include "utils/StringBuffer.h"
#include "utils/HashMap.h"

typedef StringBuffer<20> String;

static void testEquality(Test& test) {
    String s("test");
    test.checkEqual(true, s == "test", "equality with c-string");
    test.checkEqual(true, s == String("test"), "equality with another string");
    test.checkEqual(true, "test" == s, "inverse equality with c-string");
    test.checkEqual(true, String("test") == s, "inverse equality with another string");
    test.checkEqual(true, s == s, "equality with itself");
}

static void testInequality(Test& test) {
    String s("test");
    test.checkEqual(false, s != "test", "inequality with c-string");
    test.checkEqual(false, s != String("test"), "inequality with another string");
    test.checkEqual(false, "test" != s, "inverse inequality with c-string");
    test.checkEqual(false, String("test") != s, "inverse inequality with another string");
    test.checkEqual(false, s != s, "inequality with itself");
}

static void testStringAppend(Test& test) {
    String s("test");
    s.append("22").append("333").append("4444");
    test.checkEqual(String("test223334444"), s, "multiple appends");
}

static void testStringAppendOverflow(Test& test) {
    StringBuffer<5> s("te");
    s.append("2").append("333").append("4444");
    test.checkEqual(StringBuffer<5>("te23"), s, "multiple appends with overflow");
    test.checkEqual(4, s.getLength(), "length after multiple appends with overflow");
}

static void testCharacters(Test& test) {
    String s("test");
    test.checkEqual('t', s[0], "character read 1");
    test.checkEqual('e', s[1], "character read 2");
    test.checkEqual('s', s[2], "character read 3");
    test.checkEqual('t', s[3], "character read 4");
}

static void testLength(Test& test) {
    String s("test");
    test.checkEqual(4, s.getLength(), "length 1");
    s.append("aaa");
    test.checkEqual(7, s.getLength(), "length 2");
}

static void testInt(Test& test) {
    String s("test");
    s.append(524).append(-37);
    test.checkEqual(String("test524-37"), s, "int append");
}

static void testOverflowConstructor(Test& test) {
    StringBuffer<5> s("12345678");
    test.checkEqual(StringBuffer<5>("1234"), s, "overflow constructor");
    test.checkEqual(4, s.getLength(), "length after overflow constructor");
}

static void testIntOverflow(Test& test) {
    StringBuffer<5> s("te");
    s.append(123456);
    test.checkEqual(StringBuffer<5>("te12"), s, "int append with overflow");
    test.checkEqual(4, s.getLength(), "length after int append with overflow");
}

static void testFloat(Test& test) {
    String s("test");
    s.append(5.2378f).append(-500.4321f);
    test.checkEqual(String("test5.24-500.43"), s, "float append");
}

static void testBool(Test& test) {
    String s("test");
    s.append(true).append(false).append(true);
    test.checkEqual(String("testtruefalsetrue"), s, "bool append");
}

static void testClear(Test& test) {
    String s("test");
    s.append(1234).clear().append("wusi").append("1234");
    test.checkEqual(String("wusi1234"), s, "clear");
}

static void testAppendChar(Test& test) {
    StringBuffer<5> s("");
    for(int i = 0; i < 20; i++) {
        s.append('a');
    }
    test.checkEqual(StringBuffer<5>("aaaa"), s, "char append with overflow");
    test.checkEqual(4, s.getLength(), "length after char append with overflow");
}

static void testHashCode(Test& test) {
    String s;
    s.append("a").append("bc").append(20).append(25.5f).append(true);
    test.checkEqual(String("abc2025.50true").hashCode(), s.hashCode(), "string modification recalculates hash 1");
    s.clear();
    test.checkEqual(String().hashCode(), s.hashCode(), "string modification recalculates hash 2");
}

static void testAsHashMapKey(Test& test) {
    HashMap<String, int, 5> map;
    map.add(String("wusi"), 3).add(String("hiThere"), 7).add(String("baum123"), 5);
    test.checkEqual(3, map.search(String("wusi"), 0), "strings works as hash key 1");
    test.checkEqual(7, map.search(String("hiThere"), 0), "strings works as hash key 2");
    test.checkEqual(5, map.search(String("baum123"), 0), "strings works as hash key 3");
    test.checkEqual(0, map.search(String("423hifd"), 0), "strings works as hash key 4");
}

void StringBufferTests::test() {
    Test test("StringBuffer");
    testEquality(test);
    testInequality(test);
    testStringAppend(test);
    testStringAppendOverflow(test);
    testCharacters(test);
    testLength(test);
    testInt(test);
    testOverflowConstructor(test);
    testIntOverflow(test);
    testFloat(test);
    testBool(test);
    testClear(test);
    testAppendChar(test);
    testHashCode(test);
    testAsHashMapKey(test);
    test.finalize();
}