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

#include "Timer.h"
#include "Benchmark.h"
#include "LazyDecodeBitmap.h"
#include "PictureBenchmark.h"
#include "PictureRenderer.h"
#include "SkCommandLineFlags.h"
#include "SkForceLinking.h"
#include "SkGraphics.h"
#include "SkStream.h"
#include "SkString.h"
#include "SkTArray.h"

typedef sk_tools::PictureRenderer::BBoxHierarchyType BBoxType;
static const int kBBoxTypeCount = sk_tools::PictureRenderer::kLast_BBoxHierarchyType + 1;


DEFINE_string2(skps, r, "", "The list of SKPs to benchmark.");
DEFINE_string(bb_types, "", "The set of bbox types to test. If empty, all are tested. "
                       "Should be one or more of none, rtree, tilegrid.");
DEFINE_int32(record, 100, "Number of times to record each SKP.");
DEFINE_int32(playback, 1, "Number of times to playback each SKP.");
DEFINE_int32(tilesize, 256, "The size of a tile.");

struct Measurement {
    SkString fName;
    double fRecordAverage[kBBoxTypeCount];
    double fPlaybackAverage[kBBoxTypeCount];
};

const char* kBBoxHierarchyTypeNames[kBBoxTypeCount] = {
    "none", // kNone_BBoxHierarchyType
    "rtree", // kRTree_BBoxHierarchyType
    "tilegrid", // kTileGrid_BBoxHierarchyType
};

static SkPicture* pic_from_path(const char path[]) {
    SkFILEStream stream(path);
    if (!stream.isValid()) {
        SkDebugf("-- Can't open '%s'\n", path);
        return NULL;
    }
    return SkPicture::CreateFromStream(&stream, &sk_tools::LazyDecodeBitmap);
}

/**
 * This function is the sink to which all work ends up going.
 * @param renderer The renderer to use to perform the work.
 *                 To measure rendering, use a TiledPictureRenderer.
 *                 To measure recording, use a RecordPictureRenderer.
 * @param bBoxType The bounding box hierarchy type to use.
 * @param pic The picture to draw to the renderer.
 * @param numRepeats The number of times to repeat the draw.
 * @param timer The timer used to benchmark the work.
 */
static void do_benchmark_work(sk_tools::PictureRenderer* renderer,
        BBoxType bBoxType,
        SkPicture* pic,
        const int numRepeats,
        Timer* timer) {
    renderer->setBBoxHierarchyType(bBoxType);
    renderer->setGridSize(FLAGS_tilesize, FLAGS_tilesize);
    renderer->init(pic, NULL, NULL, NULL, false);

    SkDebugf("%s %d times...\n", renderer->getConfigName().c_str(), numRepeats);
    for (int i = 0; i < numRepeats; ++i) {
        renderer->setup();
        // Render once to fill caches
        renderer->render();
        // Render again to measure
        timer->start();
        renderer->render();
        timer->end();
    }
}

int tool_main(int argc, char** argv);
int tool_main(int argc, char** argv) {
    SkCommandLineFlags::Parse(argc, argv);
    SkAutoGraphics ag;
    bool includeBBoxType[kBBoxTypeCount];
    for (int bBoxType = 0; bBoxType < kBBoxTypeCount; ++bBoxType) {
        includeBBoxType[bBoxType] = (FLAGS_bb_types.count() == 0) ||
            FLAGS_bb_types.contains(kBBoxHierarchyTypeNames[bBoxType]);
    }
    // go through all the pictures
    SkTArray<Measurement> measurements;
    for (int index = 0; index < FLAGS_skps.count(); ++index) {
        const char* path = FLAGS_skps[index];
        SkPicture* picture = pic_from_path(path);
        if (NULL == picture) {
            SkDebugf("Couldn't create picture. Ignoring path: %s\n", path);
            continue;
        }
        SkDebugf("Benchmarking path: %s\n", path);
        Measurement& measurement = measurements.push_back();
        measurement.fName = path;
        for (int bBoxType = 0; bBoxType < kBBoxTypeCount; ++bBoxType) {
            if (!includeBBoxType[bBoxType]) { continue; }
            if (FLAGS_playback > 0) {
#if SK_SUPPORT_GPU
                GrContext::Options grContextOpts;
                sk_tools::TiledPictureRenderer playbackRenderer(grContextOpts);
#else
                sk_tools::TiledPictureRenderer playbackRenderer;
#endif
                Timer playbackTimer;
                do_benchmark_work(&playbackRenderer, (BBoxType)bBoxType,
                                  picture, FLAGS_playback, &playbackTimer);
                measurement.fPlaybackAverage[bBoxType] = playbackTimer.fCpu;
            }
            if (FLAGS_record > 0) {
#if SK_SUPPORT_GPU
                GrContext::Options grContextOpts;
                sk_tools::RecordPictureRenderer recordRenderer(grContextOpts);
#else
                sk_tools::RecordPictureRenderer recordRenderer;
#endif
                Timer recordTimer;
                do_benchmark_work(&recordRenderer, (BBoxType)bBoxType,
                                  picture, FLAGS_record, &recordTimer);
                measurement.fRecordAverage[bBoxType] = recordTimer.fCpu;
            }
        }
    }

    Measurement globalMeasurement;
    for (int bBoxType = 0; bBoxType < kBBoxTypeCount; ++bBoxType) {
        if (!includeBBoxType[bBoxType]) { continue; }
        globalMeasurement.fPlaybackAverage[bBoxType] = 0;
        globalMeasurement.fRecordAverage[bBoxType] = 0;
        for (int index = 0; index < measurements.count(); ++index) {
            const Measurement& measurement = measurements[index];
            globalMeasurement.fPlaybackAverage[bBoxType] +=
                measurement.fPlaybackAverage[bBoxType];
            globalMeasurement.fRecordAverage[bBoxType] +=
                measurement.fRecordAverage[bBoxType];
        }
        globalMeasurement.fPlaybackAverage[bBoxType] /= measurements.count();
        globalMeasurement.fRecordAverage[bBoxType] /= measurements.count();
    }

    // Output gnuplot readable histogram data..
    const char* pbTitle = "bbh_shootout_playback.dat";
    const char* recTitle = "bbh_shootout_record.dat";
    SkFILEWStream playbackOut(pbTitle);
    SkFILEWStream recordOut(recTitle);
    recordOut.writeText("# ");
    playbackOut.writeText("# ");
    SkDebugf("---\n");
    for (int bBoxType = 0; bBoxType < kBBoxTypeCount; ++bBoxType) {
        if (!includeBBoxType[bBoxType]) { continue; }
        SkString out;
        out.printf("%s ", kBBoxHierarchyTypeNames[bBoxType]);
        recordOut.writeText(out.c_str());
        playbackOut.writeText(out.c_str());

        if (FLAGS_record > 0) {
            SkDebugf("Average %s recording time: %.3fms\n",
                kBBoxHierarchyTypeNames[bBoxType],
                globalMeasurement.fRecordAverage[bBoxType]);
        }
        if (FLAGS_playback > 0) {
            SkDebugf("Average %s playback time: %.3fms\n",
                kBBoxHierarchyTypeNames[bBoxType],
                globalMeasurement.fPlaybackAverage[bBoxType]);
        }
    }
    recordOut.writeText("\n");
    playbackOut.writeText("\n");
    // Write to file, and save recording averages.
    for (int index = 0; index < measurements.count(); ++index) {
        const Measurement& measurement = measurements[index];
        SkString pbLine;
        SkString recLine;

        pbLine.printf("%d", index);
        recLine.printf("%d", index);
        for (int bBoxType = 0; bBoxType < kBBoxTypeCount; ++bBoxType) {
            if (!includeBBoxType[bBoxType]) { continue; }
            pbLine.appendf(" %f", measurement.fPlaybackAverage[bBoxType]);
            recLine.appendf(" %f", measurement.fRecordAverage[bBoxType]);
        }
        pbLine.appendf("\n");
        recLine.appendf("\n");
        playbackOut.writeText(pbLine.c_str());
        recordOut.writeText(recLine.c_str());
    }
    SkDebugf("\nWrote data to gnuplot-readable files: %s %s\n", pbTitle, recTitle);
    return 0;
}

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