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

#include "tools/debugger/JsonWriteBuffer.h"

#include "include/core/SkFlattenable.h"
#include "include/core/SkPoint.h"
#include "include/core/SkSamplingOptions.h"
#include "include/core/SkString.h"
#include "src/utils/SkJSONWriter.h"
#include "tools/debugger/DrawCommand.h"

class SkImage;
class SkMatrix;
class SkPaint;
class SkRegion;
class SkStream;
class SkTypeface;
struct SkIRect;
struct SkPoint3;
struct SkRect;

void JsonWriteBuffer::append(const char* type) {
    SkString fullName = SkStringPrintf("%02d_%s", fCount++, type);
    fWriter->appendName(fullName.c_str());
}

void JsonWriteBuffer::writePad32(const void* data, size_t size) {
    this->append("rawBytes");
    fWriter->beginArray();
    const uint8_t* bytes = reinterpret_cast<const uint8_t*>(data);
    for (size_t i = 0; i < size; ++i) {
        SkString hexByte = SkStringPrintf("%02x", bytes[i]);
        fWriter->appendString(hexByte);
    }
    fWriter->endArray();
}

void JsonWriteBuffer::writeByteArray(const void* data, size_t size) {
    this->append("byteArray");
    fWriter->beginArray();
    const uint8_t* bytes = reinterpret_cast<const uint8_t*>(data);
    for (size_t i = 0; i < size; ++i) {
        SkString hexByte = SkStringPrintf("%02x", bytes[i]);
        fWriter->appendString(hexByte);
    }
    fWriter->endArray();
}

void JsonWriteBuffer::writeBool(bool value) {
    this->append("bool");
    fWriter->appendBool(value);
}

void JsonWriteBuffer::writeScalar(SkScalar value) {
    this->append("scalar");
    fWriter->appendFloat(value);
}

void JsonWriteBuffer::writeScalarArray(const SkScalar* value, uint32_t count) {
    this->append("scalarArray");
    fWriter->beginArray();
    for (uint32_t i = 0; i < count; ++i) {
        fWriter->appendFloat(value[i]);
    }
    fWriter->endArray();
}

void JsonWriteBuffer::writeInt(int32_t value) {
    this->append("int");
    fWriter->appendS32(value);
}

void JsonWriteBuffer::writeIntArray(const int32_t* value, uint32_t count) {
    this->append("intArray");
    fWriter->beginArray();
    for (uint32_t i = 0; i < count; ++i) {
        fWriter->appendS32(value[i]);
    }
    fWriter->endArray();
}

void JsonWriteBuffer::writeUInt(uint32_t value) {
    this->append("uint");
    fWriter->appendU32(value);
}

void JsonWriteBuffer::writeString(std::string_view value) {
    this->append("string");
    fWriter->appendString(value.data(), value.size());
}

void JsonWriteBuffer::writeFlattenable(const SkFlattenable* flattenable) {
    if (flattenable) {
        this->append(flattenable->getTypeName());
        fWriter->beginObject();
        JsonWriteBuffer flattenableBuffer(fWriter, fUrlDataManager);
        flattenable->flatten(flattenableBuffer);
        fWriter->endObject();
    } else {
        this->append("flattenable");
        fWriter->appendPointer(nullptr);
    }
}

void JsonWriteBuffer::writeColor(SkColor color) {
    this->append("color");
    DrawCommand::MakeJsonColor(*fWriter, color);
}

void JsonWriteBuffer::writeColorArray(const SkColor* color, uint32_t count) {
    this->append("colorArray");
    fWriter->beginArray();
    for (uint32_t i = 0; i < count; ++i) {
        DrawCommand::MakeJsonColor(*fWriter, color[i]);
    }
    fWriter->endArray();
}

void JsonWriteBuffer::writeColor4f(const SkColor4f& color) {
    this->append("color");
    DrawCommand::MakeJsonColor4f(*fWriter, color);
}

void JsonWriteBuffer::writeColor4fArray(const SkColor4f* color, uint32_t count) {
    this->append("colorArray");
    fWriter->beginArray();
    for (uint32_t i = 0; i < count; ++i) {
        DrawCommand::MakeJsonColor4f(*fWriter, color[i]);
    }
    fWriter->endArray();
}

void JsonWriteBuffer::writePoint(const SkPoint& point) {
    this->append("point");
    DrawCommand::MakeJsonPoint(*fWriter, point);
}

void JsonWriteBuffer::writePoint3(const SkPoint3& point) {
    this->append("point3");
    DrawCommand::MakeJsonPoint3(*fWriter, point);
}

void JsonWriteBuffer::writePointArray(const SkPoint* point, uint32_t count) {
    this->append("pointArray");
    fWriter->beginArray();
    for (uint32_t i = 0; i < count; ++i) {
        DrawCommand::MakeJsonPoint(*fWriter, point[i]);
    }
    fWriter->endArray();
}

void JsonWriteBuffer::write(const SkM44& matrix) {
    this->append("matrix");
    fWriter->beginArray();
    for (int r = 0; r < 4; ++r) {
        fWriter->beginArray(nullptr, false);
        SkV4 v = matrix.row(r);
        for (int c = 0; c < 4; ++c) {
            fWriter->appendFloat(v[c]);
        }
        fWriter->endArray();
    }
    fWriter->endArray();
}

void JsonWriteBuffer::writeMatrix(const SkMatrix& matrix) {
    this->append("matrix");
    DrawCommand::MakeJsonMatrix(*fWriter, matrix);
}

void JsonWriteBuffer::writeIRect(const SkIRect& rect) {
    this->append("irect");
    DrawCommand::MakeJsonIRect(*fWriter, rect);
}

void JsonWriteBuffer::writeRect(const SkRect& rect) {
    this->append("rect");
    DrawCommand::MakeJsonRect(*fWriter, rect);
}

void JsonWriteBuffer::writeRegion(const SkRegion& region) {
    this->append("region");
    DrawCommand::MakeJsonRegion(*fWriter, region);
}

void JsonWriteBuffer::writePath(const SkPath& path) {
    this->append("path");
    DrawCommand::MakeJsonPath(*fWriter, path);
}

void JsonWriteBuffer::writeSampling(const SkSamplingOptions& sampling) {
    this->append("sampling");
    DrawCommand::MakeJsonSampling(*fWriter, sampling);
}

size_t JsonWriteBuffer::writeStream(SkStream* stream, size_t length) {
    // Contents not supported
    this->append("stream");
    fWriter->appendU64(static_cast<uint64_t>(length));
    return 0;
}

void JsonWriteBuffer::writeImage(const SkImage* image) {
    this->append("image");
    fWriter->beginObject();
    DrawCommand::flatten(*image, *fWriter, *fUrlDataManager);
    fWriter->endObject();
}

void JsonWriteBuffer::writeTypeface(SkTypeface* typeface) {
    // Unsupported
    this->append("typeface");
    fWriter->appendPointer(typeface);
}

void JsonWriteBuffer::writePaint(const SkPaint& paint) {
    this->append("paint");
    DrawCommand::MakeJsonPaint(*fWriter, paint, *fUrlDataManager);
}
