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

#include "dm/DMJsonWriter.h"

#include "include/core/SkData.h"
#include "include/core/SkStream.h"
#include "include/private/base/SkMutex.h"
#include "include/private/base/SkTArray.h"
#include "src/core/SkOSFile.h"
#include "src/utils/SkJSON.h"
#include "src/utils/SkJSONWriter.h"
#include "src/utils/SkOSPath.h"
#include "tools/ProcStats.h"

namespace DM {

SkTArray<JsonWriter::BitmapResult> gBitmapResults;
static SkMutex& bitmap_result_mutex() {
    static SkMutex& mutex = *(new SkMutex);
    return mutex;
}


void JsonWriter::AddBitmapResult(const BitmapResult& result) {
    SkAutoMutexExclusive lock(bitmap_result_mutex());
    gBitmapResults.push_back(result);
}

void JsonWriter::DumpJson(const char* dir,
                          CommandLineFlags::StringArray key,
                          CommandLineFlags::StringArray properties) {
    if (0 == strcmp(dir, "")) {
        return;
    }

    SkString path = SkOSPath::Join(dir, "dm.json");
    sk_mkdir(dir);
    SkFILEWStream stream(path.c_str());
    SkJSONWriter writer(&stream, SkJSONWriter::Mode::kPretty);

    writer.beginObject(); // root

    for (int i = 1; i < properties.size(); i += 2) {
        writer.appendCString(properties[i-1], properties[i]);
    }

    writer.beginObject("key");
    for (int i = 1; i < key.size(); i += 2) {
        writer.appendCString(key[i-1], key[i]);
    }
    writer.endObject();

    int maxResidentSetSizeMB = sk_tools::getMaxResidentSetSizeMB();
    if (maxResidentSetSizeMB != -1) {
        writer.appendS32("max_rss_MB", maxResidentSetSizeMB);
    }

    {
        SkAutoMutexExclusive lock(bitmap_result_mutex());
        writer.beginArray("results");
        for (int i = 0; i < gBitmapResults.size(); i++) {
            writer.beginObject();

            writer.beginObject("key");
            writer.appendString("name"       , gBitmapResults[i].name);
            writer.appendString("config"     , gBitmapResults[i].config);
            writer.appendString("source_type", gBitmapResults[i].sourceType);

            // Source options only need to be part of the key if they exist.
            // Source type by source type, we either always set options or never set options.
            if (!gBitmapResults[i].sourceOptions.isEmpty()) {
                writer.appendString("source_options", gBitmapResults[i].sourceOptions);
            }
            writer.endObject(); // key

            writer.beginObject("options");
            writer.appendString("ext"  ,       gBitmapResults[i].ext);
            writer.appendString("gamut",       gBitmapResults[i].gamut);
            writer.appendString("transfer_fn", gBitmapResults[i].transferFn);
            writer.appendString("color_type",  gBitmapResults[i].colorType);
            writer.appendString("alpha_type",  gBitmapResults[i].alphaType);
            writer.appendString("color_depth", gBitmapResults[i].colorDepth);
            writer.endObject(); // options

            writer.appendString("md5", gBitmapResults[i].md5);

            writer.endObject(); // 1 result
        }
        writer.endArray(); // results
    }

    writer.endObject(); // root
    writer.flush();
    stream.flush();
}

using namespace skjson;

bool JsonWriter::ReadJson(const char* path, void(*callback)(BitmapResult)) {
    sk_sp<SkData> json(SkData::MakeFromFileName(path));
    if (!json) {
        return false;
    }

    DOM dom((const char*)json->data(), json->size());
    const ObjectValue* root = dom.root();
    if (!root) {
        return false;
    }

    const ArrayValue* results = (*root)["results"];
    if (!results) {
        return false;
    }

    BitmapResult br;
    for (const ObjectValue* r : *results) {
        const ObjectValue& key = (*r)["key"].as<ObjectValue>();
        const ObjectValue& options = (*r)["options"].as<ObjectValue>();

        br.name         = key["name"].as<StringValue>().begin();
        br.config       = key["config"].as<StringValue>().begin();
        br.sourceType   = key["source_type"].as<StringValue>().begin();
        br.ext          = options["ext"].as<StringValue>().begin();
        br.gamut        = options["gamut"].as<StringValue>().begin();
        br.transferFn   = options["transfer_fn"].as<StringValue>().begin();
        br.colorType    = options["color_type"].as<StringValue>().begin();
        br.alphaType    = options["alpha_type"].as<StringValue>().begin();
        br.colorDepth   = options["color_depth"].as<StringValue>().begin();
        br.md5          = (*r)["md5"].as<StringValue>().begin();

        if (const StringValue* so = key["source_options"]) {
            br.sourceOptions = so->begin();
        }
        callback(br);
    }
    return true;
}

} // namespace DM
