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

#include <VisualBench/VisualBenchmarkStream.h>
#include <VisualBench/WrappedBenchmark.h>
#include "GMBench.h"
#include "SkOSFile.h"
#include "SkPath.h"
#include "SkPictureRecorder.h"
#include "SkStream.h"
#include "sk_tool_utils.h"
#include "VisualFlags.h"
#include "VisualSKPBench.h"

#if SK_SUPPORT_GPU
#include "GrContext.h"
#endif

DEFINE_string2(match, m, nullptr,
               "[~][^]substring[$] [...] of bench name to run.\n"
               "Multiple matches may be separated by spaces.\n"
               "~ causes a matching bench to always be skipped\n"
               "^ requires the start of the bench to match\n"
               "$ requires the end of the bench to match\n"
               "^ and $ requires an exact match\n"
               "If a bench does not match any list entry,\n"
               "it is skipped unless some list entry starts with ~");
DEFINE_string(skps, "skps", "Directory to read skps from.");
DEFINE_bool(warmup, true, "Include a warmup bench? (Excluding the warmup may compromise results)");

// We draw a big nonAA path to warmup the gpu / cpu
#include "SkPerlinNoiseShader.h"
class WarmupBench : public Benchmark {
public:
    WarmupBench() {
        sk_tool_utils::make_big_path(fPath);
        fPerlinRect = SkRect::MakeLTRB(0., 0., 400., 400.);
    }
private:
    const char* onGetName() override { return "warmupbench"; }
    SkIPoint onGetSize() override {
        int w = SkScalarCeilToInt(SkTMax(fPath.getBounds().right(), fPerlinRect.right()));
        int h = SkScalarCeilToInt(SkTMax(fPath.getBounds().bottom(), fPerlinRect.bottom()));
        return SkIPoint::Make(w, h);
    }
    void onDraw(int loops, SkCanvas* canvas) override {
        // We draw a big path to warm up the cpu, and then use perlin noise shader to warm up the
        // gpu
        SkPaint paint;
        paint.setStyle(SkPaint::kStroke_Style);
        paint.setStrokeWidth(2);

        SkPaint perlinPaint;
        perlinPaint.setShader(SkPerlinNoiseShader::MakeTurbulence(0.1f, 0.1f, 1, 0, nullptr));
        for (int i = 0; i < loops; i++) {
            canvas->drawPath(fPath, paint);
            canvas->drawRect(fPerlinRect, perlinPaint);
#if SK_SUPPORT_GPU
            // Ensure the GrContext doesn't batch across draw loops.
            if (GrContext* context = canvas->getGrContext()) {
                context->flush();
            }
#endif
        }
    }
    SkPath fPath;
    SkRect fPerlinRect;
};

VisualBenchmarkStream::VisualBenchmarkStream(const SkSurfaceProps& surfaceProps, bool justSKP)
    : fSurfaceProps(surfaceProps)
    , fBenches(BenchRegistry::Head())
    , fGMs(skiagm::GMRegistry::Head())
    , fSourceType(nullptr)
    , fBenchType(nullptr)
    , fCurrentSKP(0)
    , fIsWarmedUp(false) {
    for (int i = 0; i < FLAGS_skps.count(); i++) {
        if (SkStrEndsWith(FLAGS_skps[i], ".skp")) {
            fSKPs.push_back() = FLAGS_skps[i];
        } else {
            SkOSFile::Iter it(FLAGS_skps[i], ".skp");
            SkString path;
            while (it.next(&path)) {
                fSKPs.push_back() = SkOSPath::Join(FLAGS_skps[0], path.c_str());
            }
        }
    }

    if (justSKP) {
       fGMs = nullptr;
       fBenches = nullptr;
    }

    // seed with an initial benchmark
    // NOTE the initial benchmark will not have preTimingHooks called, but that is okay because
    // it is the warmupbench
    this->next();
}

sk_sp<SkPicture> VisualBenchmarkStream::ReadPicture(const char path[]) {
    // Not strictly necessary, as it will be checked again later,
    // but helps to avoid a lot of pointless work if we're going to skip it.
    if (SkCommandLineFlags::ShouldSkip(FLAGS_match, path)) {
        return nullptr;
    }

    SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(path));
    if (stream.get() == nullptr) {
        SkDebugf("Could not read %s.\n", path);
        return nullptr;
    }

    auto pic = SkPicture::MakeFromStream(stream.get());
    if (!pic) {
        SkDebugf("Could not read %s as an SkPicture.\n", path);
    }
    return pic;
}

Benchmark* VisualBenchmarkStream::next() {
    Benchmark* bench;
    if (FLAGS_warmup && !fIsWarmedUp) {
        fIsWarmedUp = true;
        bench = new WarmupBench;
    } else {
        // skips non matching benches
        while ((bench = this->innerNext()) &&
               (SkCommandLineFlags::ShouldSkip(FLAGS_match, bench->getUniqueName()) ||
                !bench->isSuitableFor(Benchmark::kGPU_Backend))) {
            bench->unref();
        }
    }

    // TODO move this all to --config
    if (bench && FLAGS_cpu) {
        bench = new CpuWrappedBenchmark(fSurfaceProps, bench);
    } else if (bench && FLAGS_offscreen) {
        bench = new GpuWrappedBenchmark(fSurfaceProps, bench, FLAGS_msaa);
    }

    fBenchmark.reset(bench);
    return fBenchmark;
}

Benchmark* VisualBenchmarkStream::innerNext() {
    while (fBenches) {
        Benchmark* bench = fBenches->factory()(nullptr);
        fBenches = fBenches->next();
        if (bench->isVisual()) {
            fSourceType = "bench";
            fBenchType  = "micro";
            return bench;
        }
        bench->unref();
    }

    while (fGMs) {
        SkAutoTDelete<skiagm::GM> gm(fGMs->factory()(nullptr));
        fGMs = fGMs->next();
        if (gm->runAsBench()) {
            fSourceType = "gm";
            fBenchType  = "micro";
            return new GMBench(gm.release());
        }
    }

    // Render skps
    while (fCurrentSKP < fSKPs.count()) {
        const SkString& path = fSKPs[fCurrentSKP++];
        sk_sp<SkPicture> pic = ReadPicture(path.c_str());
        if (!pic) {
            continue;
        }

        SkString name = SkOSPath::Basename(path.c_str());
        fSourceType = "skp";
        fBenchType = "playback";
        return new VisualSKPBench(name.c_str(), pic.get());
    }

    return nullptr;
}
