/*
 * Copyright 2013 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 *
 * Classes for writing out bench results in various formats.
 */

#ifndef SkResultsWriter_DEFINED
#define SkResultsWriter_DEFINED

#include "BenchLogger.h"
#include "SkJSONCPP.h"
#include "SkOSFile.h"
#include "SkOSPath.h"
#include "SkStream.h"
#include "SkString.h"
#include "SkTypes.h"

/**
 * Base class for writing out the bench results.
 *
 * Default implementation does nothing.
 */
class ResultsWriter : SkNoncopyable {
public:
    virtual ~ResultsWriter() {}

    // Record one key value pair that makes up a unique key for this type of run, e.g.
    // builder name, machine type, Debug/Release, etc.
    virtual void key(const char name[], const char value[]) {}

    // Record one key value pair that describes the run instance, e.g. git hash, build number.
    virtual void property(const char name[], const char value[]) {}

    // Denote the start of a specific benchmark. Once bench is called,
    // then config and metric can be called multiple times to record runs.
    virtual void bench(const char name[], int32_t x, int32_t y) {}

    // Record the specific configuration a bench is run under, such as "8888".
    virtual void config(const char name[]) {}

    // Record the options for a configuration, such as "GL_RENDERER".
    virtual void configOption(const char name[], const char* value) {}

    // Record a single test metric.
    virtual void metric(const char name[], double ms) {}

    // Record a list of test metrics.
    virtual void metrics(const char name[], const SkTArray<double>& array) {}

    // Flush to storage now please.
    virtual void flush() {}
};

/**
 NanoJSONResultsWriter writes the test results out in the following
 format:

 {
    "key": {
      "arch": "Arm7",
      "gpu": "SGX540",
      "os": "Android",
      "model": "GalaxyNexus",
    }
    "gitHash": "d1830323662ae8ae06908b97f15180fd25808894",
    "build_number": "1234",
    "results" : {
        "Xfermode_Luminosity_640_480" : {
           "8888" : {
                 "median_ms" : 143.188128906250,
                 "min_ms" : 143.835957031250,
                 ...
              },
          ...
*/
class NanoJSONResultsWriter : public ResultsWriter {
public:
    explicit NanoJSONResultsWriter(const char filename[])
        : fFilename(filename)
        , fRoot()
        , fResults(fRoot["results"])
        , fBench(nullptr)
        , fConfig(nullptr) {}

    ~NanoJSONResultsWriter() override {
        this->flush();
    }

    // Added under "key".
    void key(const char name[], const char value[]) override {
        fRoot["key"][name] = value;
    }
    // Inserted directly into the root.
    void property(const char name[], const char value[]) override {
        fRoot[name] = value;
    }
    void bench(const char name[], int32_t x, int32_t y) override {
        SkString id = SkStringPrintf( "%s_%d_%d", name, x, y);
        fResults[id.c_str()] = Json::Value(Json::objectValue);
        fBench = &fResults[id.c_str()];
    }
    void config(const char name[]) override {
        SkASSERT(fBench);
        fConfig = &(*fBench)[name];
    }
    void configOption(const char name[], const char* value) override {
        (*fConfig)["options"][name] = value;
    }
    void metric(const char name[], double ms) override {
        // Don't record if nan, or -nan.
        if (sk_double_isnan(ms)) {
            return;
        }
        SkASSERT(fConfig);
        (*fConfig)[name] = ms;
    }
    void metrics(const char name[], const SkTArray<double>& array) override {
        SkASSERT(fConfig);
        Json::Value value = Json::Value(Json::arrayValue);
        value.resize(array.count());
        for (int i = 0; i < array.count(); i++) {
            // Don't care about nan-ness.
            value[i] = array[i];
        }
        (*fConfig)[name] = std::move(value);
    }

    // Flush to storage now please.
    void flush() override {
        SkString dirname = SkOSPath::Dirname(fFilename.c_str());
        if (!sk_exists(dirname.c_str(), kWrite_SkFILE_Flag)) {
            if (!sk_mkdir(dirname.c_str())) {
                SkDebugf("Failed to create directory.");
            }
        }
        SkFILEWStream stream(fFilename.c_str());
        stream.writeText(Json::StyledWriter().write(fRoot).c_str());
        stream.flush();
    }

private:
    SkString fFilename;
    Json::Value fRoot;
    Json::Value& fResults;
    Json::Value* fBench;
    Json::Value* fConfig;
};


#endif
