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

#include "SkChromeTracingTracer.h"
#include "SkJSONWriter.h"
#include "SkThreadID.h"
#include "SkTraceEvent.h"
#include "SkOSFile.h"
#include "SkOSPath.h"
#include "SkStream.h"

#include <chrono>

namespace {

/**
 * All events have a fixed block of information (TraceEvent), plus variable length payload:
 * {TraceEvent} {TraceEventArgs} {Inline Payload}
 */
struct TraceEventArg {
    uint8_t fArgType;
    const char* fArgName;
    uint64_t fArgValue;
};

// These fields are ordered to minimize size due to alignment. Argument types could be packed
// better, but very few events have many arguments, so the net loss is pretty small.
struct TraceEvent {
    char fPhase;
    uint8_t fNumArgs;
    uint32_t fSize;

    const char* fName;
    // TODO: Merge fID and fClockEnd (never used together)
    uint64_t fID;
    uint64_t fClockBegin;
    uint64_t fClockEnd;
    SkThreadID fThreadID;

    TraceEvent* next() {
        return reinterpret_cast<TraceEvent*>(reinterpret_cast<char*>(this) + fSize);
    }
    TraceEventArg* args() {
        return reinterpret_cast<TraceEventArg*>(this + 1);
    }
    char* stringTable() {
        return reinterpret_cast<char*>(this->args() + fNumArgs);
    }
};

}

SkChromeTracingTracer::SkChromeTracingTracer(const char* filename) : fFilename(filename) {
    this->createBlock();
}

SkChromeTracingTracer::~SkChromeTracingTracer() {
    this->flush();
}

void SkChromeTracingTracer::createBlock() {
    fCurBlock.fBlock = BlockPtr(new uint8_t[kBlockSize]);
    fCurBlock.fEventsInBlock = 0;
    fCurBlockUsed = 0;
}

SkEventTracer::Handle SkChromeTracingTracer::appendEvent(const void* data, size_t size) {
    SkASSERT(size > 0 && size <= kBlockSize);

    SkAutoMutexAcquire lock(fMutex);
    if (fCurBlockUsed + size > kBlockSize) {
        fBlocks.push_back(std::move(fCurBlock));
        this->createBlock();
    }
    memcpy(fCurBlock.fBlock.get() + fCurBlockUsed, data, size);
    Handle handle = reinterpret_cast<Handle>(fCurBlock.fBlock.get() + fCurBlockUsed);
    fCurBlockUsed += size;
    fCurBlock.fEventsInBlock++;
    return handle;
}

SkEventTracer::Handle SkChromeTracingTracer::addTraceEvent(char phase,
                                                           const uint8_t* categoryEnabledFlag,
                                                           const char* name,
                                                           uint64_t id,
                                                           int numArgs,
                                                           const char** argNames,
                                                           const uint8_t* argTypes,
                                                           const uint64_t* argValues,
                                                           uint8_t flags) {
    // TODO: Respect flags (or assert). INSTANT events encode scope in flags, should be stored
    // using "s" key in JSON. COPY flag should be supported or rejected.

    // Figure out how much extra storage we need for copied strings
    int size = static_cast<int>(sizeof(TraceEvent) + numArgs * sizeof(TraceEventArg));
    for (int i = 0; i < numArgs; ++i) {
        if (TRACE_VALUE_TYPE_COPY_STRING == argTypes[i]) {
            skia::tracing_internals::TraceValueUnion value;
            value.as_uint = argValues[i];
            size += strlen(value.as_string) + 1;
        }
    }

    size = SkAlign8(size);

    SkSTArray<128, uint8_t, true> storage;
    uint8_t* storagePtr = storage.push_back_n(size);

    TraceEvent* traceEvent = reinterpret_cast<TraceEvent*>(storagePtr);
    traceEvent->fPhase = phase;
    traceEvent->fNumArgs = numArgs;
    traceEvent->fSize = size;
    traceEvent->fName = name;
    traceEvent->fID = id;
    traceEvent->fClockBegin = std::chrono::steady_clock::now().time_since_epoch().count();
    traceEvent->fClockEnd = 0;
    traceEvent->fThreadID = SkGetThreadID();

    TraceEventArg* traceEventArgs = traceEvent->args();
    char* stringTableBase = traceEvent->stringTable();
    char* stringTable = stringTableBase;
    for (int i = 0; i < numArgs; ++i) {
        traceEventArgs[i].fArgName = argNames[i];
        traceEventArgs[i].fArgType = argTypes[i];
        if (TRACE_VALUE_TYPE_COPY_STRING == argTypes[i]) {
            // Just write an offset into the arguments array
            traceEventArgs[i].fArgValue = stringTable  - stringTableBase;

            // Copy string into our buffer (and advance)
            skia::tracing_internals::TraceValueUnion value;
            value.as_uint = argValues[i];
            while (*value.as_string) {
                *stringTable++ = *value.as_string++;
            }
            *stringTable++ = 0;
        } else {
            traceEventArgs[i].fArgValue = argValues[i];
        }
    }

    return this->appendEvent(storagePtr, size);
}

void SkChromeTracingTracer::updateTraceEventDuration(const uint8_t* categoryEnabledFlag,
                                                     const char* name,
                                                     SkEventTracer::Handle handle) {
    // We could probably get away with not locking here, but let's be totally safe.
    SkAutoMutexAcquire lock(fMutex);
    TraceEvent* traceEvent = reinterpret_cast<TraceEvent*>(handle);
    traceEvent->fClockEnd = std::chrono::steady_clock::now().time_since_epoch().count();
}

static void trace_value_to_json(SkJSONWriter* writer, uint64_t argValue, uint8_t argType,
                                const char* stringTableBase) {
    skia::tracing_internals::TraceValueUnion value;
    value.as_uint = argValue;

    switch (argType) {
        case TRACE_VALUE_TYPE_BOOL:
            writer->appendBool(value.as_bool);
            break;
        case TRACE_VALUE_TYPE_UINT:
            writer->appendU64(value.as_uint);
            break;
        case TRACE_VALUE_TYPE_INT:
            writer->appendS64(value.as_int);
            break;
        case TRACE_VALUE_TYPE_DOUBLE:
            writer->appendDouble(value.as_double);
            break;
        case TRACE_VALUE_TYPE_POINTER:
            writer->appendPointer(value.as_pointer);
            break;
        case TRACE_VALUE_TYPE_STRING:
            writer->appendString(value.as_string);
            break;
        case TRACE_VALUE_TYPE_COPY_STRING:
            writer->appendString(stringTableBase + value.as_uint);
            break;
        default:
            writer->appendString("<unknown type>");
            break;
    }
}

namespace {

struct TraceEventSerializationState {
    TraceEventSerializationState(uint64_t clockOffset)
            : fClockOffset(clockOffset), fNextThreadID(0) {}

    int getShortThreadID(SkThreadID id) {
        if (int* shortIDPtr = fShortThreadIDMap.find(id)) {
            return *shortIDPtr;
        }
        int shortID = fNextThreadID++;
        fShortThreadIDMap.set(id, shortID);
        return shortID;
    }

    uint64_t fClockOffset;
    SkTHashMap<uint64_t, const char*> fBaseTypeResolver;
    int fNextThreadID;
    SkTHashMap<SkThreadID, int> fShortThreadIDMap;
};

}

static void trace_event_to_json(SkJSONWriter* writer, TraceEvent* traceEvent,
                                TraceEventSerializationState* serializationState) {
    // We track the original (creation time) "name" of each currently live object, so we can
    // automatically insert "base_name" fields in object snapshot events.
    auto baseTypeResolver = &(serializationState->fBaseTypeResolver);
    if (TRACE_EVENT_PHASE_CREATE_OBJECT == traceEvent->fPhase) {
        SkASSERT(nullptr == baseTypeResolver->find(traceEvent->fID));
        baseTypeResolver->set(traceEvent->fID, traceEvent->fName);
    } else if (TRACE_EVENT_PHASE_DELETE_OBJECT == traceEvent->fPhase) {
        SkASSERT(nullptr != baseTypeResolver->find(traceEvent->fID));
        baseTypeResolver->remove(traceEvent->fID);
    }

    writer->beginObject();

    char phaseString[2] = { traceEvent->fPhase, 0 };
    writer->appendString("ph", phaseString);
    writer->appendString("name", traceEvent->fName);
    if (0 != traceEvent->fID) {
        // IDs are (almost) always pointers
        writer->appendPointer("id", reinterpret_cast<void*>(traceEvent->fID));
    }

    // Offset timestamps to reduce JSON length, then convert nanoseconds to microseconds
    // (standard time unit for tracing JSON files).
    uint64_t relativeTimestamp = static_cast<int64_t>(traceEvent->fClockBegin -
                                                      serializationState->fClockOffset);
    writer->appendDoubleDigits("ts", static_cast<double>(relativeTimestamp) * 1E-3, 3);
    if (0 != traceEvent->fClockEnd) {
        double dur = static_cast<double>(traceEvent->fClockEnd - traceEvent->fClockBegin) * 1E-3;
        writer->appendDoubleDigits("dur", dur, 3);
    }

    writer->appendS64("tid", serializationState->getShortThreadID(traceEvent->fThreadID));
    // Trace events *must* include a process ID, but for internal tools this isn't particularly
    // important (and certainly not worth adding a cross-platform API to get it).
    writer->appendS32("pid", 0);

    if (traceEvent->fNumArgs) {
        writer->beginObject("args");
        const char* stringTable = traceEvent->stringTable();
        bool addedSnapshot = false;
        if (TRACE_EVENT_PHASE_SNAPSHOT_OBJECT == traceEvent->fPhase &&
                baseTypeResolver->find(traceEvent->fID) &&
                0 != strcmp(*baseTypeResolver->find(traceEvent->fID), traceEvent->fName)) {
            // Special handling for snapshots where the name differs from creation.
            writer->beginObject("snapshot");
            writer->appendString("base_type", *baseTypeResolver->find(traceEvent->fID));
            addedSnapshot = true;
        }

        for (int i = 0; i < traceEvent->fNumArgs; ++i) {
            const TraceEventArg* arg = traceEvent->args() + i;
            // TODO: Skip '#'
            writer->appendName(arg->fArgName);

            if (arg->fArgName && '#' == arg->fArgName[0]) {
                writer->beginObject();
                writer->appendName("id_ref");
                trace_value_to_json(writer, arg->fArgValue, arg->fArgType, stringTable);
                writer->endObject();
            } else {
                trace_value_to_json(writer, arg->fArgValue, arg->fArgType, stringTable);
            }
        }

        if (addedSnapshot) {
            writer->endObject();
        }

        writer->endObject();
    }

    writer->endObject();
}

void SkChromeTracingTracer::flush() {
    SkAutoMutexAcquire lock(fMutex);

    SkString dirname = SkOSPath::Dirname(fFilename.c_str());
    if (!dirname.isEmpty() && !sk_exists(dirname.c_str(), kWrite_SkFILE_Flag)) {
        if (!sk_mkdir(dirname.c_str())) {
            SkDebugf("Failed to create directory.");
        }
    }

    SkFILEWStream fileStream(fFilename.c_str());
    SkJSONWriter writer(&fileStream, SkJSONWriter::Mode::kFast);
    writer.beginArray();

    uint64_t clockOffset = 0;
    if (fBlocks.count() > 0) {
        clockOffset = reinterpret_cast<TraceEvent*>(fBlocks[0].fBlock.get())->fClockBegin;
    } else if (fCurBlock.fEventsInBlock > 0) {
        clockOffset = reinterpret_cast<TraceEvent*>(fCurBlock.fBlock.get())->fClockBegin;
    }

    TraceEventSerializationState serializationState(clockOffset);

    auto event_block_to_json = [](SkJSONWriter* writer, const TraceEventBlock& block,
                                  TraceEventSerializationState* serializationState) {
        TraceEvent* traceEvent = reinterpret_cast<TraceEvent*>(block.fBlock.get());
        for (int i = 0; i < block.fEventsInBlock; ++i) {
            trace_event_to_json(writer, traceEvent, serializationState);
            traceEvent = traceEvent->next();
        }
    };

    for (int i = 0; i < fBlocks.count(); ++i) {
        event_block_to_json(&writer, fBlocks[i], &serializationState);
    }
    event_block_to_json(&writer, fCurBlock, &serializationState);

    writer.endArray();
    writer.flush();
    fileStream.flush();
}
