/*
 * Copyright 2017 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include <iostream>
#include <sys/stat.h>

#include "skqp.h"

#include "Resources.h"
#include "SkData.h"
#include "SkOSFile.h"

////////////////////////////////////////////////////////////////////////////////

namespace {
class StdAssetManager : public SkQPAssetManager {
public:
    StdAssetManager(const char* p) : fPrefix(p) {
        SkASSERT(!fPrefix.empty());
        //TODO(halcanary): does this need to be changed if I run SkQP in Windows?
        fPrefix += "/";
    }
    sk_sp<SkData> open(const char* path) override {
        return SkData::MakeFromFileName((fPrefix + path).c_str());
    }
private:
    std::string fPrefix;
};
}

static constexpr char kSkipUsage[] =
    " TEST_MATCH_RULES:"
    "    [~][^]substring[$] [...] of name to run.\n"
    "    Multiple matches may be separated by spaces.\n"
    "    ~ causes a matching name to always be skipped\n"
    "    ^ requires the start of the name to match\n"
    "    $ requires the end of the name to match\n"
    "    ^ and $ requires an exact match\n"
    "    If a name does not match any list entry,\n"
    "    it is skipped unless some list entry starts with ~\n";

static bool should_skip(const char* const* rules, size_t count, const char* name) {
    size_t testLen = strlen(name);
    bool anyExclude = count == 0;
    for (size_t i = 0; i < count; ++i) {
        const char* matchName = rules[i];
        size_t matchLen = strlen(matchName);
        bool matchExclude, matchStart, matchEnd;
        if ((matchExclude = matchName[0] == '~')) {
            anyExclude = true;
            matchName++;
            matchLen--;
        }
        if ((matchStart = matchName[0] == '^')) {
            matchName++;
            matchLen--;
        }
        if ((matchEnd = matchName[matchLen - 1] == '$')) {
            matchLen--;
        }
        if (matchStart ? (!matchEnd || matchLen == testLen)
                && strncmp(name, matchName, matchLen) == 0
                : matchEnd ? matchLen <= testLen
                && strncmp(name + testLen - matchLen, matchName, matchLen) == 0
                : strstr(name, matchName) != nullptr) {
            return matchExclude;
        }
    }
    return !anyExclude;
}

int main(int argc, char** argv) {
    if (argc < 3) {
        std::cerr << "Usage:\n  " << argv[0]
                  << " ASSET_DIRECTORY_PATH SKQP_REPORT_PATH [TEST_MATCH_RULES]\n"
                  << kSkipUsage << '\n';
        return 1;
    }
    SetResourcePath((std::string(argv[1]) + "/resources").c_str());
    if (!sk_mkdir(argv[2])) {
        std::cerr << "sk_mkdir(" << argv[2] << ") failed.\n";
        return 2;
    }
    StdAssetManager mgr(argv[1]);
    SkQP skqp;
    skqp.init(&mgr, argv[2]);
    int ret = 0;

    const char* const* matchRules = &argv[3];
    size_t matchRulesCount = (size_t)(argc - 3);

    // Rendering Tests
    std::ostream& out = std::cout;
    for (auto backend : skqp.getSupportedBackends()) {
        auto testPrefix = std::string(SkQP::GetBackendName(backend)) + "_";
        for (auto gmFactory : skqp.getGMs()) {
            auto testName = testPrefix + SkQP::GetGMName(gmFactory);
            if (should_skip(matchRules, matchRulesCount, testName.c_str())) {
                continue;
            }
            out << "Starting: " << testName << std::endl;
            SkQP::RenderOutcome outcome;
            std::string except;

            std::tie(outcome, except) = skqp.evaluateGM(backend, gmFactory);
            if (!except.empty()) {
                out << "ERROR:    " << testName << " (" << except << ")\n";
                ret = 1;
            } else if (outcome.fMaxError != 0) {
                out << "FAILED:   " << testName << " (" << outcome.fMaxError << ")\n";
                ret = 1;
            } else {
                out << "Passed:   " << testName << "\n";
            }
            out.flush();
        }
    }

    // Unit Tests
    for (auto test : skqp.getUnitTests()) {
        auto testName = std::string("unitTest_") +  SkQP::GetUnitTestName(test);
        if (should_skip(matchRules, matchRulesCount, testName.c_str())) {
            continue;
        }
        out << "Starting test: " << testName << std::endl;
        std::vector<std::string> errors = skqp.executeTest(test);
        if (!errors.empty()) {
            out << "TEST FAILED (" << errors.size() << "): " << testName << "\n";
            for (const std::string& error : errors) {
                out << error << "\n";
            }
            ret = 1;
        } else {
            out << "Test passed:   " << testName << "\n";
        }
        out.flush();
    }
    skqp.makeReport();

    return ret;
}
