#include <cstring>

#include "../Tests.hpp"
#include "../src/ErrorSimulator.hpp"
#include "core/File.hpp"
#include "core/Logger.hpp"
#include "core/Test.hpp"

static int failIndex = 0;
static const char* fails[] = {
    "cannot read file 'gdfgdfg'",
    "cannot seek file end of 'testData/someFile'",
    "cannot tell file position of 'testData/someFile'",
    "cannot seek file start of 'testData/someFile'",
    "expected to read 20 bytes from 'testData/someFile' but read 20",
    "cannot close file 'testData/someFile'"};

static void printReport(
    LogLevel l, const char*, int, void*, const char* message) {
    TEST(static_cast<int>(LogLevel::ERROR), static_cast<int>(l));
    if(!TEST_TRUE(strstr(message, fails[failIndex]) != nullptr)) {
        LOG_ERROR("'#' does not contain '#'", message, fails[failIndex]);
    }
}

static void testExistingFile() {
    Core::List<char> f;
    if(!TEST_FALSE(readFile(f, "testData/someFile"))) {
        return;
    }
    TEST(21lu, f.getLength());
    TEST_STRING("Just\nSome\nTest File\n", &f[0]);
}

static void testNotExistingFile() {
    Core::List<char> f;
    TEST_TRUE(readFile(f, "gdfgdfg"));
}

static void testFails(int steps) {
    (void)steps;
#ifdef ERROR_SIMULATOR
    failStep = steps;
    failIndex = steps;
    Core::List<char> f;
    TEST_TRUE(readFile(f, "testData/someFile"));
    failStep = -1;
#endif
}

void testFile() {
    setReportHandler(printReport, nullptr);
    testExistingFile();
    testNotExistingFile();
    for(int i = 1; i < 6; i++) {
        testFails(i);
    }
    setReportHandler(nullptr, nullptr);
}