// Main binary for DM.
// For a high-level overview, please see dm/README.

#include "GrContext.h"
#include "GrContextFactory.h"
#include "SkCommandLineFlags.h"
#include "SkForceLinking.h"
#include "SkGraphics.h"
#include "SkString.h"
#include "gm.h"

#include "DMReporter.h"
#include "DMTask.h"
#include "DMTaskRunner.h"
#include "DMCpuTask.h"
#include "DMGpuTask.h"

#include <string.h>

using skiagm::GM;
using skiagm::GMRegistry;
using skiagm::Expectations;
using skiagm::ExpectationsSource;
using skiagm::JsonExpectationsSource;

DEFINE_int32(cpuThreads, -1, "Threads for CPU work. Default NUM_CPUS.");
DEFINE_int32(gpuThreads, 1, "Threads for GPU work.");
DEFINE_string(expectations, "", "Compare generated images against JSON expectations at this path.");
DEFINE_string(resources, "resources", "Path to resources directory.");
DEFINE_string(match, "",  "[~][^]substring[$] [...] of GM name to run.\n"
                          "Multiple matches may be separated by spaces.\n"
                          "~ causes a matching GM to always be skipped\n"
                          "^ requires the start of the GM to match\n"
                          "$ requires the end of the GM to match\n"
                          "^ and $ requires an exact match\n"
                          "If a GM does not match any list entry,\n"
                          "it is skipped unless some list entry starts with ~");
DEFINE_string(config, "8888 gpu",
        "Options: 565 8888 gpu msaa4 msaa16 gpunull gpudebug angle mesa"); // TODO(mtklein): pdf

__SK_FORCE_IMAGE_DECODER_LINKING;

// "FooBar" -> "foobar".  Obviously, ASCII only.
static SkString lowercase(SkString s) {
    for (size_t i = 0; i < s.size(); i++) {
        s[i] = tolower(s[i]);
    }
    return s;
}

static void kick_off_tasks(const SkTDArray<GMRegistry::Factory>& gms,
                           const SkTArray<SkString>& configs,
                           const ExpectationsSource& expectations,
                           DM::Reporter* reporter,
                           DM::TaskRunner* tasks) {
    const SkBitmap::Config _565 = SkBitmap::kRGB_565_Config;
    const SkBitmap::Config _8888 = SkBitmap::kARGB_8888_Config;
    const GrContextFactory::GLContextType native = GrContextFactory::kNative_GLContextType;
    const GrContextFactory::GLContextType null   = GrContextFactory::kNull_GLContextType;
    const GrContextFactory::GLContextType debug  = GrContextFactory::kDebug_GLContextType;
    const GrContextFactory::GLContextType angle  =
    #if SK_ANGLE
        GrContextFactory::kANGLE_GLContextType;
    #else
        native;
    #endif
    const GrContextFactory::GLContextType mesa   =
    #if SK_MESA
        GLContextFactory::kMESA_GLContextType;
    #else
        native;
    #endif

    for (int i = 0; i < gms.count(); i++) {
#define START(name, type, ...)                                                     \
    if (lowercase(configs[j]).equals(name)) {                                      \
        tasks->add(SkNEW_ARGS(DM::type,                                            \
                    (name, reporter, tasks, expectations, gms[i], __VA_ARGS__)));  \
    }
        for (int j = 0; j < configs.count(); j++) {
            START("565",      CpuTask, _565);
            START("8888",     CpuTask, _8888);
            START("gpu",      GpuTask, _8888, native, 0);
            START("msaa4",    GpuTask, _8888, native, 4);
            START("msaa16",   GpuTask, _8888, native, 16);
            START("gpunull",  GpuTask, _8888, null,   0);
            START("gpudebug", GpuTask, _8888, debug,  0);
            START("angle",    GpuTask, _8888, angle,  0);
            START("mesa",     GpuTask, _8888, mesa,   0);
            //START("pdf",      PdfTask, _8888);
        }
    }
#undef START
}

static void report_failures(const DM::Reporter& reporter) {
    SkTArray<SkString> failures;
    reporter.getFailures(&failures);

    if (failures.count() == 0) {
        return;
    }

    SkDebugf("Failures:\n");
    for (int i = 0; i < failures.count(); i++) {
        SkDebugf("  %s\n", failures[i].c_str());
    }
}

class NoExpectations : public ExpectationsSource {
public:
    Expectations get(const char* /*testName*/) const SK_OVERRIDE {
        return Expectations();
    }
};

int tool_main(int argc, char** argv);
int tool_main(int argc, char** argv) {
    SkGraphics::Init();

    SkCommandLineFlags::Parse(argc, argv);
    GM::SetResourcePath(FLAGS_resources[0]);
    SkTArray<SkString> configs;
    for (int i = 0; i < FLAGS_config.count(); i++) {
        SkStrSplit(FLAGS_config[i], ", ", &configs);
    }

    SkTDArray<GMRegistry::Factory> gms;
    for (const GMRegistry* reg = GMRegistry::Head(); reg != NULL; reg = reg->next()) {
        SkAutoTDelete<GM> gmForName(reg->factory()(NULL));
        if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, gmForName->shortName())) {
            *gms.append() = reg->factory();
        }
    }
    SkDebugf("%d GMs x %d configs\n", gms.count(), configs.count());

    SkAutoTUnref<ExpectationsSource> expectations(SkNEW(NoExpectations));
    if (FLAGS_expectations.count() > 0) {
        expectations.reset(SkNEW_ARGS(JsonExpectationsSource, (FLAGS_expectations[0])));
    }

    DM::Reporter reporter;
    DM::TaskRunner tasks(FLAGS_cpuThreads, FLAGS_gpuThreads);
    kick_off_tasks(gms, configs, *expectations, &reporter, &tasks);
    tasks.wait();

    reporter.updateStatusLine();
    SkDebugf("\n");
    report_failures(reporter);

    SkGraphics::Term();

    return reporter.failed() > 0;
}

#if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL)
int main(int argc, char** argv) {
    return tool_main(argc, argv);
}
#endif
