/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "call_observer.h"

#include <tuple>

#include "spy_base.h"

using gapic::coder::memory::Range;
using gapic::Interval;

namespace {

// Minimum byte gap between memory observations before globbing together.
const size_t MEMORY_MERGE_THRESHOLD = 256;

// Size of the temporary heap buffer to use when the scratch stack buffer is
// filled.
const size_t SCRATCH_BUFFER_SIZE = 512*1024;

// Maximum size of the CallObserver's extras list.
const size_t MAX_EXTRAS = 16;

// Buffer creating function for scratch allocator.
std::tuple<uint8_t*, size_t> createBuffer(size_t request_size,
                                                 size_t min_buffer_size) {
    size_t size =
        request_size > min_buffer_size ? request_size : min_buffer_size;
    return std::make_tuple(new uint8_t[size], size);
}

// Buffer releasing function for scratch allocator.
void releaseBuffer(uint8_t* buffer) { delete[] buffer; }

}  // anonymous namespace

namespace gapii {
// Creates a CallObserver with a given spy and applies the memory space for
// observation data from the spy instance.
CallObserver::CallObserver(SpyBase* spy_p)
    : mSpyPtr(spy_p),
      mCurrentCommandName(nullptr),
      mObserveApplicationPool(spy_p->shouldObserveApplicationPool()),
      mScratch(
          [](size_t size) { return createBuffer(size, SCRATCH_BUFFER_SIZE); },
          [](uint8_t* buffer) { return releaseBuffer(buffer); }),
      mObservations(nullptr),
      mError(GLenum::GL_NO_ERROR) {
    mPendingObservations.setMergeThreshold(MEMORY_MERGE_THRESHOLD);
    mExtras = mScratch.vector<gapic::Encodable*>(MAX_EXTRAS);
}

// Releases the observation data memory at the end.
CallObserver::~CallObserver() {}

void CallObserver::read(const void* base, uint64_t size) {
    if (size > 0) {
        uintptr_t start = reinterpret_cast<uintptr_t>(base);
        uintptr_t end = start + static_cast<uintptr_t>(size);
        mPendingObservations.merge(Interval<uintptr_t>{start, end});
    }
}

void CallObserver::write(const void* base, uint64_t size) {
    if (size > 0) {
        uintptr_t start = reinterpret_cast<uintptr_t>(base);
        uintptr_t end = start + static_cast<uintptr_t>(size);
        mPendingObservations.merge(Interval<uintptr_t>{start, end});
    }
}

void CallObserver::observe(gapic::Vector<Observation>& observations) {
    observations = mScratch.vector<Observation>(mPendingObservations.count());
    for (auto p : mPendingObservations) {
        gapic::Vector<uint8_t> data(reinterpret_cast<uint8_t*>(p.start()),
                                    p.end() - p.start());
        gapic::Id id = gapic::Id::Hash(data.data(), data.count());
        if (mSpyPtr->getResources().count(id) == 0) {
            gapic::coder::atom::Resource resource(id, data);
            mSpyPtr->getEncoder()->Variant(&resource);
            mSpyPtr->getResources().emplace(id);
        }
        observations.append(Observation(Range(p.start(), data.count()), id));
    }
    mPendingObservations.clear();
}
}  // namespace gapii
