#include "filedb/cistring.h"
#include "filedb/database_tables.h"

#include <tango/tango.h>

#include <catch2/catch_test_macros.hpp>
#include <catch2/catch_translate_exception.hpp>

SCENARIO("Record can view single ident parts")
{
    GIVEN("A record ident \"foo/bar/baz\"")
    {
        FileDb::Record record{"foo/bar/baz"};

        WHEN("We ask for the first part")
        {
            FileDb::cistring_view part = record.view_ident_parts(0);
            THEN("We get \"foo\"")
            {
                REQUIRE(part == "foo");
            }
        }

        WHEN("We ask for the second part")
        {
            FileDb::cistring_view part = record.view_ident_parts(1);
            THEN("We get \"bar\"")
            {
                REQUIRE(part == "bar");
            }
        }

        WHEN("We ask for the third part")
        {
            FileDb::cistring_view part = record.view_ident_parts(2);
            THEN("We get \"baz\"")
            {
                REQUIRE(part == "baz");
            }
        }

        WHEN("We ask for the forth part")
        {
            FileDb::cistring_view part = record.view_ident_parts(3);
            THEN("We get \"\"")
            {
                REQUIRE(part == "");
            }
        }

        WHEN("We ask for the fifth part")
        {
            FileDb::cistring_view part = record.view_ident_parts(4);
            THEN("We get \"\"")
            {
                REQUIRE(part == "");
            }
        }
    }
}

SCENARIO("Record can view multiple ident parts")
{
    GIVEN("A record ident \"foo/bar/baz\"")
    {
        FileDb::Record record{"foo/bar/baz"};

        WHEN("We ask for the first two parts")
        {
            FileDb::cistring_view part = record.view_ident_parts(0, 2);
            THEN("We get \"foo/bar\"")
            {
                REQUIRE(part == "foo/bar");
            }
        }

        WHEN("We ask for the second two parts")
        {
            FileDb::cistring_view part = record.view_ident_parts(1, 2);
            THEN("We get \"bar/baz\"")
            {
                REQUIRE(part == "bar/baz");
            }
        }

        WHEN("We ask for the third two parts")
        {
            FileDb::cistring_view part = record.view_ident_parts(2, 2);
            THEN("We get \"baz\"")
            {
                REQUIRE(part == "baz");
            }
        }

        WHEN("We ask for the forth two parts part")
        {
            FileDb::cistring_view part = record.view_ident_parts(3, 2);
            THEN("We get \"\"")
            {
                REQUIRE(part == "");
            }
        }

        WHEN("We ask for the first four parts")
        {
            FileDb::cistring_view part = record.view_ident_parts(0, 4);
            THEN("We get \"foo/bar/baz\"")
            {
                REQUIRE(part == "foo/bar/baz");
            }
        }
    }
}

SCENARIO("Wildcard can match empty globs")
{
    GIVEN("An empty wildcard")
    {
        FileDb::Wildcard wildcard{""};

        WHEN("We test an empty string")
        {
            const char *test = "";

            THEN("We get a match")
            {
                REQUIRE(wildcard(test));
            }
        }

        WHEN("We test a non-empty string")
        {
            const char *test = "foo";

            THEN("We do not get a match")
            {
                REQUIRE(!wildcard(test));
            }
        }
    }
}

SCENARIO("Wildcard can match literals")
{
    GIVEN("A wildcard with no *")
    {
        FileDb::Wildcard wildcard{"foo"};

        WHEN("We test the string itself")
        {
            const char *test = "foo";
            THEN("We get a match")
            {
                REQUIRE(wildcard(test));
            }
        }

        WHEN("We test a string with a prefix")
        {
            const char *test = "prefix_foo";

            THEN("We do not get a match")
            {
                REQUIRE(!wildcard(test));
            }
        }

        WHEN("We test a string with a suffix")
        {
            const char *test = "foo_suffix";

            THEN("We do not get a match")
            {
                REQUIRE(!wildcard(test));
            }
        }
    }
}

SCENARIO("Wildcard can match glob prefixes")
{
    GIVEN("A wildcard with a * at the start")
    {
        FileDb::Wildcard wildcard{"*foo"};

        WHEN("We test the string itself")
        {
            const char *test = "foo";
            THEN("We get a match")
            {
                REQUIRE(wildcard(test));
            }
        }

        WHEN("We test a string with a prefix")
        {
            const char *test = "prefix_foo";

            THEN("We get a match")
            {
                REQUIRE(wildcard(test));
            }
        }

        WHEN("We test a string with a suffix")
        {
            const char *test = "foo_suffix";

            THEN("We do not get a match")
            {
                REQUIRE(!wildcard(test));
            }
        }
    }
}

SCENARIO("Wildcard can match glob suffixes")
{
    GIVEN("A wildcard with a * at the end")
    {
        FileDb::Wildcard wildcard{"foo*"};

        WHEN("We test the string itself")
        {
            const char *test = "foo";
            THEN("We get a match")
            {
                REQUIRE(wildcard(test));
            }
        }

        WHEN("We test a string with a prefix")
        {
            const char *test = "prefix_foo";

            THEN("We do not get a match")
            {
                REQUIRE(!wildcard(test));
            }
        }

        WHEN("We test a string with a suffix")
        {
            const char *test = "foo_suffix";

            THEN("We get a match")
            {
                REQUIRE(wildcard(test));
            }
        }
    }
}

SCENARIO("Wildcard can match glob infixes")
{
    GIVEN("A wildcard with a * in the middle")
    {
        FileDb::Wildcard wildcard{"foo*bar"};

        WHEN("We test the string itself")
        {
            const char *test = "foobar";
            THEN("We get a match")
            {
                REQUIRE(wildcard(test));
            }
        }

        WHEN("We test a string with a prefix")
        {
            const char *test = "prefix_foobar";

            THEN("We do not get a match")
            {
                REQUIRE(!wildcard(test));
            }
        }

        WHEN("We test a string with a suffix")
        {
            const char *test = "foobar_suffix";

            THEN("We do not get a match")
            {
                REQUIRE(!wildcard(test));
            }
        }

        WHEN("We test a string with an infix")
        {
            const char *test = "foo_infix_bar";

            THEN("We get a match")
            {
                REQUIRE(wildcard(test));
            }
        }
    }
}

SCENARIO("Wildcard can match complex globs")
{
    GIVEN("A more complex wildcard")
    {
        FileDb::Wildcard wildcard{"*foo*bar*"};

        WHEN("We test the string itself")
        {
            const char *test = "foobar";
            THEN("We get a match")
            {
                REQUIRE(wildcard(test));
            }
        }

        WHEN("We test a string with a prefix")
        {
            const char *test = "prefix_foobar";

            THEN("We get a match")
            {
                REQUIRE(wildcard(test));
            }
        }

        WHEN("We test a string with a suffix")
        {
            const char *test = "foobar_suffix";

            THEN("We get a match")
            {
                REQUIRE(wildcard(test));
            }
        }

        WHEN("We test a string with an infix")
        {
            const char *test = "foo_infix_bar";

            THEN("We get a match")
            {
                REQUIRE(wildcard(test));
            }
        }

        WHEN("We test a string missing a peice")
        {
            const char *test = "foo";

            THEN("We do not get a match")
            {
                REQUIRE(!wildcard(test));
            }
        }
    }
}
