/*
 * 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 "GrAuditTrail.h"
#include "ops/GrOp.h"
#include "SkJSONWriter.h"

const int GrAuditTrail::kGrAuditTrailInvalidID = -1;

void GrAuditTrail::addOp(const GrOp* op, GrRenderTargetProxy::UniqueID proxyID) {
    SkASSERT(fEnabled);
    Op* auditOp = new Op;
    fOpPool.emplace_back(auditOp);
    auditOp->fName = op->name();
    auditOp->fBounds = op->bounds();
    auditOp->fClientID = kGrAuditTrailInvalidID;
    auditOp->fOpListID = kGrAuditTrailInvalidID;
    auditOp->fChildID = kGrAuditTrailInvalidID;

    // consume the current stack trace if any
    auditOp->fStackTrace = fCurrentStackTrace;
    fCurrentStackTrace.reset();

    if (fClientID != kGrAuditTrailInvalidID) {
        auditOp->fClientID = fClientID;
        Ops** opsLookup = fClientIDLookup.find(fClientID);
        Ops* ops = nullptr;
        if (!opsLookup) {
            ops = new Ops;
            fClientIDLookup.set(fClientID, ops);
        } else {
            ops = *opsLookup;
        }

        ops->push_back(auditOp);
    }

    // Our algorithm doesn't bother to reorder inside of an OpNode so the ChildID will start at 0
    auditOp->fOpListID = fOpList.count();
    auditOp->fChildID = 0;

    // We use the op pointer as a key to find the OpNode we are 'glomming' ops onto
    fIDLookup.set(op->uniqueID(), auditOp->fOpListID);
    OpNode* opNode = new OpNode(proxyID);
    opNode->fBounds = op->bounds();
    opNode->fChildren.push_back(auditOp);
    fOpList.emplace_back(opNode);
}

void GrAuditTrail::opsCombined(const GrOp* consumer, const GrOp* consumed) {
    // Look up the op we are going to glom onto
    int* indexPtr = fIDLookup.find(consumer->uniqueID());
    SkASSERT(indexPtr);
    int index = *indexPtr;
    SkASSERT(index < fOpList.count() && fOpList[index]);
    OpNode& consumerOp = *fOpList[index];

    // Look up the op which will be glommed
    int* consumedPtr = fIDLookup.find(consumed->uniqueID());
    SkASSERT(consumedPtr);
    int consumedIndex = *consumedPtr;
    SkASSERT(consumedIndex < fOpList.count() && fOpList[consumedIndex]);
    OpNode& consumedOp = *fOpList[consumedIndex];

    // steal all of consumed's ops
    for (int i = 0; i < consumedOp.fChildren.count(); i++) {
        Op* childOp = consumedOp.fChildren[i];

        // set the ids for the child op
        childOp->fOpListID = index;
        childOp->fChildID = consumerOp.fChildren.count();
        consumerOp.fChildren.push_back(childOp);
    }

    // Update the bounds for the combineWith node
    consumerOp.fBounds = consumer->bounds();

    // remove the old node from our opList and clear the combinee's lookup
    // NOTE: because we can't change the shape of the oplist, we use a sentinel
    fOpList[consumedIndex].reset(nullptr);
    fIDLookup.remove(consumed->uniqueID());
}

void GrAuditTrail::copyOutFromOpList(OpInfo* outOpInfo, int opListID) {
    SkASSERT(opListID < fOpList.count());
    const OpNode* bn = fOpList[opListID].get();
    SkASSERT(bn);
    outOpInfo->fBounds = bn->fBounds;
    outOpInfo->fProxyUniqueID    = bn->fProxyUniqueID;
    for (int j = 0; j < bn->fChildren.count(); j++) {
        OpInfo::Op& outOp = outOpInfo->fOps.push_back();
        const Op* currentOp = bn->fChildren[j];
        outOp.fBounds = currentOp->fBounds;
        outOp.fClientID = currentOp->fClientID;
    }
}

void GrAuditTrail::getBoundsByClientID(SkTArray<OpInfo>* outInfo, int clientID) {
    Ops** opsLookup = fClientIDLookup.find(clientID);
    if (opsLookup) {
        // We track which oplistID we're currently looking at.  If it changes, then we need to push
        // back a new op info struct.  We happen to know that ops are in sequential order in the
        // oplist, otherwise we'd have to do more bookkeeping
        int currentOpListID = kGrAuditTrailInvalidID;
        for (int i = 0; i < (*opsLookup)->count(); i++) {
            const Op* op = (**opsLookup)[i];

            // Because we will copy out all of the ops associated with a given op list id everytime
            // the id changes, we only have to update our struct when the id changes.
            if (kGrAuditTrailInvalidID == currentOpListID || op->fOpListID != currentOpListID) {
                OpInfo& outOpInfo = outInfo->push_back();

                // copy out all of the ops so the client can display them even if they have a
                // different clientID
                this->copyOutFromOpList(&outOpInfo, op->fOpListID);
            }
        }
    }
}

void GrAuditTrail::getBoundsByOpListID(OpInfo* outInfo, int opListID) {
    this->copyOutFromOpList(outInfo, opListID);
}

void GrAuditTrail::fullReset() {
    SkASSERT(fEnabled);
    fOpList.reset();
    fIDLookup.reset();
    // free all client ops
    fClientIDLookup.foreach ([](const int&, Ops** ops) { delete *ops; });
    fClientIDLookup.reset();
    fOpPool.reset();  // must be last, frees all of the memory
}

template <typename T>
void GrAuditTrail::JsonifyTArray(SkJSONWriter& writer, const char* name, const T& array) {
    if (array.count()) {
        writer.beginArray(name);
        for (int i = 0; i < array.count(); i++) {
            // Handle sentinel nullptrs
            if (array[i]) {
                array[i]->toJson(writer);
            }
        }
        writer.endArray();
    }
}

void GrAuditTrail::toJson(SkJSONWriter& writer) const {
    writer.beginObject();
    JsonifyTArray(writer, "Ops", fOpList);
    writer.endObject();
}

void GrAuditTrail::toJson(SkJSONWriter& writer, int clientID) const {
    writer.beginObject();
    Ops** ops = fClientIDLookup.find(clientID);
    if (ops) {
        JsonifyTArray(writer, "Ops", **ops);
    }
    writer.endObject();
}

static void skrect_to_json(SkJSONWriter& writer, const char* name, const SkRect& rect) {
    writer.beginObject(name);
    writer.appendFloat("Left", rect.fLeft);
    writer.appendFloat("Right", rect.fRight);
    writer.appendFloat("Top", rect.fTop);
    writer.appendFloat("Bottom", rect.fBottom);
    writer.endObject();
}

void GrAuditTrail::Op::toJson(SkJSONWriter& writer) const {
    writer.beginObject();
    writer.appendString("Name", fName.c_str());
    writer.appendS32("ClientID", fClientID);
    writer.appendS32("OpListID", fOpListID);
    writer.appendS32("ChildID", fChildID);
    skrect_to_json(writer, "Bounds", fBounds);
    if (fStackTrace.count()) {
        writer.beginArray("Stack");
        for (int i = 0; i < fStackTrace.count(); i++) {
            writer.appendString(fStackTrace[i].c_str());
        }
        writer.endArray();
    }
    writer.endObject();
}

void GrAuditTrail::OpNode::toJson(SkJSONWriter& writer) const {
    writer.beginObject();
    writer.appendU32("ProxyID", fProxyUniqueID.asUInt());
    skrect_to_json(writer, "Bounds", fBounds);
    JsonifyTArray(writer, "Ops", fChildren);
    writer.endObject();
}
