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

#include "src/core/SkRTree.h"

#include "include/private/SkAssert.h"
#include "include/private/SkDebug.h"

SkRTree::SkRTree() : fCount(0) {}

void SkRTree::insert(const SkRect boundsArray[], int N) {
    SkASSERT(0 == fCount);

    std::vector<Branch> branches;
    branches.reserve(N);

    for (int i = 0; i < N; i++) {
        const SkRect& bounds = boundsArray[i];
        if (bounds.isEmpty()) {
            continue;
        }

        Branch b;
        b.fBounds = bounds;
        b.fOpIndex = i;
        branches.push_back(b);
    }

    fCount = (int)branches.size();
    if (fCount) {
        if (1 == fCount) {
            fNodes.reserve(1);
            Node* n = this->allocateNodeAtLevel(0);
            n->fNumChildren = 1;
            n->fChildren[0] = branches[0];
            fRoot.fSubtree = n;
            fRoot.fBounds  = branches[0].fBounds;
        } else {
            fNodes.reserve(CountNodes(fCount));
            fRoot = this->bulkLoad(&branches);
        }
    }
}

SkRTree::Node* SkRTree::allocateNodeAtLevel(uint16_t level) {
    SkDEBUGCODE(Node* p = fNodes.data());
    fNodes.push_back(Node{});
    Node& out = fNodes.back();
    SkASSERT(fNodes.data() == p);  // If this fails, we didn't reserve() enough.
    out.fNumChildren = 0;
    out.fLevel = level;
    return &out;
}

// This function parallels bulkLoad, but just counts how many nodes bulkLoad would allocate.
int SkRTree::CountNodes(int branches) {
    if (branches == 1) {
        return 1;
    }
    int remainder   = branches % kMaxChildren;
    if (remainder > 0) {
        if (remainder >= kMinChildren) {
            remainder = 0;
        } else {
            remainder = kMinChildren - remainder;
        }
    }
    int currentBranch = 0;
    int nodes = 0;
    while (currentBranch < branches) {
        int incrementBy = kMaxChildren;
        if (remainder != 0) {
            if (remainder <= kMaxChildren - kMinChildren) {
                incrementBy -= remainder;
                remainder = 0;
            } else {
                incrementBy = kMinChildren;
                remainder -= kMaxChildren - kMinChildren;
            }
        }
        nodes++;
        currentBranch++;
        for (int k = 1; k < incrementBy && currentBranch < branches; ++k) {
            currentBranch++;
        }
    }
    return nodes + CountNodes(nodes);
}

SkRTree::Branch SkRTree::bulkLoad(std::vector<Branch>* branches, int level) {
    if (branches->size() == 1) { // Only one branch.  It will be the root.
        return (*branches)[0];
    }

    // We might sort our branches here, but we expect Blink gives us a reasonable x,y order.
    // Skipping a call to sort (in Y) here resulted in a 17% win for recording with negligible
    // difference in playback speed.
    int remainder   = (int)branches->size() % kMaxChildren;
    int newBranches = 0;

    if (remainder > 0) {
        // If the remainder isn't enough to fill a node, we'll add fewer nodes to other branches.
        if (remainder >= kMinChildren) {
            remainder = 0;
        } else {
            remainder = kMinChildren - remainder;
        }
    }

    int currentBranch = 0;
    while (currentBranch < (int)branches->size()) {
        int incrementBy = kMaxChildren;
        if (remainder != 0) {
            // if need be, omit some nodes to make up for remainder
            if (remainder <= kMaxChildren - kMinChildren) {
                incrementBy -= remainder;
                remainder = 0;
            } else {
                incrementBy = kMinChildren;
                remainder -= kMaxChildren - kMinChildren;
            }
        }
        Node* n = allocateNodeAtLevel(level);
        n->fNumChildren = 1;
        n->fChildren[0] = (*branches)[currentBranch];
        Branch b;
        b.fBounds = (*branches)[currentBranch].fBounds;
        b.fSubtree = n;
        ++currentBranch;
        for (int k = 1; k < incrementBy && currentBranch < (int)branches->size(); ++k) {
            b.fBounds.join((*branches)[currentBranch].fBounds);
            n->fChildren[k] = (*branches)[currentBranch];
            ++n->fNumChildren;
            ++currentBranch;
        }
        (*branches)[newBranches] = b;
        ++newBranches;
    }
    branches->resize(newBranches);
    return this->bulkLoad(branches, level + 1);
}

void SkRTree::search(const SkRect& query, std::vector<int>* results) const {
    if (fCount > 0 && SkRect::Intersects(fRoot.fBounds, query)) {
        this->search(fRoot.fSubtree, query, results);
    }
}

void SkRTree::search(Node* node, const SkRect& query, std::vector<int>* results) const {
    for (int i = 0; i < node->fNumChildren; ++i) {
        if (SkRect::Intersects(node->fChildren[i].fBounds, query)) {
            if (0 == node->fLevel) {
                results->push_back(node->fChildren[i].fOpIndex);
            } else {
                this->search(node->fChildren[i].fSubtree, query, results);
            }
        }
    }
}

size_t SkRTree::bytesUsed() const {
    size_t byteCount = sizeof(SkRTree);

    byteCount += fNodes.capacity() * sizeof(Node);

    return byteCount;
}
