//
//  OmMathAndCollectionsTests.cpp
//  OmUtil
//
//  Created by David Van Brink on 1/8/17.
//  Copyright (c) 2017 omino.com. All rights reserved.
//

#include "OmMathAndCollectionsTests.h"
#include "Om.h"
#include "OmAsserts.h"



OMTEST(testGcd)
{
    ASSERT_EQUALS_INT("gcd", 2, gcd(86, 64));
    ASSERT_EQUALS_INT("gcd", 20, gcd(100, 120));
}

OMTEST(doIndexOf)
{
    std::vector<int> x = {1,2,3,4,5,6,7,8};
    ASSERT_EQUALS_INT("indexof", 5, indexOf(x, 6));
    ASSERT_EQUALS_INT("indexof", -1, indexOf(x, 100));
    
    std::vector<std::string> y = {"fish", "dog", "cat"};
    ASSERT_EQUALS_INT("indexof", 1, indexOf(y, std::string("dog")));
    ASSERT_EQUALS_INT("indexof", -1, indexOf(y, std::string("dogx")));
}

OMTEST(doRemove)
{
    std::vector<int> x = {1,2,3,4,5,6,7,8};
    removeItem(x, 3); // 1 2 4 5 6 7 8
    removeItem(x, 10);
    removeItem(x, -1);
    remove(x, 0); // 2 4 5 6 7 8
    remove(x, 10);
    remove(x, -1);
    ASSERT_EQUALS_INT("count", 6, x.size());
    ASSERT_EQUALS_INT("item", 2, x[0]);
    ASSERT_EQUALS_INT("item", 4, x[1]);
    ASSERT_EQUALS_INT("item", 5, x[2]);
    
    std::vector<std::string> y = {"fish", "dog", "cat"};
    removeItem(y, "dog");
    removeItem(y, "xdog");
    remove(y, 0);
    remove(y, 10);
    remove(y, -10);
    ASSERT_EQUALS_INT("count", 1, y.size());
    ASSERT_EQUALS_STRING("item", "cat", y[0]);
}

OMTEST(doContains)
{
    std::vector<int> x = {1,2,3,4,5,6,7,8};
    ASSERT_FALSE("contains", contains(x, 86));
    ASSERT_TRUE("contains", contains(x, 8));
}


OMTEST(testNumberOfBits)
{
    ASSERT_EQUALS_INT("number of bits", 0, numberOfBits(0));
    ASSERT_EQUALS_INT("number of bits", 1, numberOfBits(1));
    ASSERT_EQUALS_INT("number of bits", 2, numberOfBits(2));
    ASSERT_EQUALS_INT("number of bits", 2, numberOfBits(3));
    ASSERT_EQUALS_INT("number of bits", 3, numberOfBits(4));
    
    ASSERT_EQUALS_INT("number of bits", 17, numberOfBits(0x10000));
    ASSERT_EQUALS_INT("number of bits", 32, numberOfBits(-1));
    ASSERT_EQUALS_INT("number of bits", 29, numberOfBits(0x12345678));
}


OMTEST(testPairsTemplates)
{
    std::map<std::string, int> mm;
    
    mm["fish"] = 1023;
    mm["bird"] = 1042;
    for(int ix = 0; ix < 20; ix++)
    {
        int v = (ix * 17) % 20; // should have them all, out of order
        v = v + 100;
        mm[ssprintf("a_%d", v)] = -v;
    }
    
    std::vector<std::pair<std::string, int>> pairs = getPairs(mm);
    ASSERT_EQUALS_INT("pairs", 22, pairs.size());
    
    
    sortSecond(pairs);
    for(int ix = 0; ix < 20; ix++)
    {
        int v = 119 - ix;
        std::string s = ssprintf("a_%d", v);
        ASSERT_EQUALS_STRING("sorted pairs?", s, pairs[ix].first);
        ASSERT_EQUALS_INT_SHUSH("sorted pairs?", -v, pairs[ix].second);
    }
    
    sortFirst(pairs);
    for(int ix = 0; ix < 20; ix++)
    {
        int v = 100 + ix;
        std::string s = ssprintf("a_%d", v);
        ASSERT_EQUALS_STRING("sorted pairs?", s, pairs[ix].first);
        ASSERT_EQUALS_INT_SHUSH("sorted pairs?", -v, pairs[ix].second);
    }
    
    std::vector<int> values = getValues(mm);
    for(int ix = 0; ix < 20; ix++)
        ASSERT_EQUALS_INT_SHUSH("values", -100 - ix, values[ix]);
    
    values = getValues(mm, true);
    for(int ix = 0; ix < 20; ix++)
        ASSERT_EQUALS_INT_SHUSH("values", -119 + ix, values[ix]);
}

OMTEST(testAntimap)
{
    std::map<std::string, int> mm;
    mm["a"] = 0xa;
    mm["b"] = 0xb;
    mm["c"] = 42;
    
    ASSERT_TRUE("contains value", containsValue(mm, 0xa));
    ASSERT_FALSE("contains value", containsValue(mm, 0xd));
    ASSERT_EQUALS_STRING("get value", "a", getKey(mm, 10));
    ASSERT_EQUALS_STRING("get value", "b", getKey(mm, 11));
    ASSERT_EQUALS_STRING("get value", "c", getKey(mm, 42));
    ASSERT_EQUALS_STRING("get value", "", getKey(mm, 44));
}


void allMathAndCollectionsTests()
{
    doIndexOf();
    doRemove();
    doContains();
    
    testGcd();
    testPairsTemplates();
    testAntimap();
    
    testNumberOfBits();

    OMTESTEND()
}
