// Copyright 2016 The Android Open Source Project
//
// This software is licensed under the terms of the GNU General Public
// License version 2, as published by the Free Software Foundation, and
// may be copied, distributed, and modified under those terms.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

#include "android/metrics/PeriodicReporter.h"

#include "android/base/memory/LazyInstance.h"

#include <iterator>
#include <type_traits>
#include <utility>

using android::base::AutoLock;
using android::base::LazyInstance;
using android::base::Looper;
using android::base::System;

namespace android {
namespace metrics {

// An instance holder object: it manages the creation of the default reporter
// instance.
struct PeriodicReporter::InstanceHolder {
    PeriodicReporter::Ptr reporter;

    InstanceHolder() : reporter(new PeriodicReporter()) {}
};

static LazyInstance<PeriodicReporter::InstanceHolder> sReporter = {};

void PeriodicReporter::start(MetricsReporter* metricsReporter, Looper* looper) {
    sReporter->reporter->startImpl(metricsReporter, looper);
}

void PeriodicReporter::stop() {
    // Make sure we create a new instance of periodic reporter here:
    // this way we expire all weak pointers in TaskGuards and they won't
    // try erasing from a list using invalid stale iterators.
    sReporter->reporter.reset(new PeriodicReporter());
}

PeriodicReporter& PeriodicReporter::get() {
    assert(sReporter->reporter.get());
    return *sReporter->reporter;
}

PeriodicReporter::PeriodicReporter() = default;

PeriodicReporter::~PeriodicReporter() {
    AutoLock lock(mLock);
    mPeriodDataByPeriod.clear();
}

void PeriodicReporter::addTask(System::Duration periodMs, Callback callback) {
    AutoLock lock(mLock);
    addTaskInternalNoLock(periodMs, std::move(callback));
}

PeriodicReporter::TaskToken PeriodicReporter::addCancelableTask(
        System::Duration periodMs,
        PeriodicReporter::Callback callback) {
    // Capture a weak pointer to |this| into the task guard to make sure it can
    // outlive |this| and won't try to call into a dangling pointer.
    const auto weakThis = WeakPtr(shared_from_this());

    AutoLock lock(mLock);
    const auto iter = addTaskInternalNoLock(periodMs, std::move(callback));
    lock.unlock();

    return std::make_shared<TaskGuard>([periodMs, iter, weakThis]() {
        if (const auto sharedThis = weakThis.lock()) {
            sharedThis->removeTask(periodMs, iter);
        }
    });
}

void PeriodicReporter::startImpl(MetricsReporter* metricsReporter,
                                 Looper* looper) {
    AutoLock lock(mLock);

    assert(!mMetricsReporter);
    assert(!mLooper);

    assert(metricsReporter);
    assert(looper);

    mMetricsReporter = metricsReporter;
    mLooper = looper;

    for (auto& periodAndData : mPeriodDataByPeriod) {
        assert(!periodAndData.second.task);

        createPerPeriodTimerNoLock(&periodAndData.second, periodAndData.first);
    }
}

void PeriodicReporter::createPerPeriodTimerNoLock(PerPeriodData* const data,
                                                  System::Duration periodMs) {
    static_assert(!std::is_reference<decltype(data)>::value,
                  "|data| must not be a reference: gcc 4.6 used to have a bug "
                  "where capturing a reference by value resulted in silent bad "
                  "code generation");

    assert(mLooper);

    auto timerFunc = [this, data]() {
        mMetricsReporter->reportConditional(
                [this, data](android_studio::AndroidStudioEvent* event) {
                    AutoLock lock(mLock);
                    bool result = false;
                    // Callback may erase itself from the list, deal with that
                    // by using raw iterators in the loop.
                    auto itCallback = data->callbacks.begin();
                    while (itCallback != data->callbacks.end()) {
                        const auto itCurrentCallback = itCallback++;
                        // As task may try removing itself, unlock
                        // the object temporarily here.
                        lock.unlock();
                        result |= (*itCurrentCallback)(event);
                        lock.lock();
                    }
                    return result;
                });
        return true;
    };

    data->task.emplace(mLooper, std::move(timerFunc), periodMs);
    data->task->start();
}

PeriodicReporter::CallbackList::iterator
PeriodicReporter::addTaskInternalNoLock(System::Duration periodMs,
                                        PeriodicReporter::Callback callback) {
    PerPeriodData& data = mPeriodDataByPeriod[periodMs];
    data.callbacks.push_back(std::move(callback));
    if (mLooper && !data.task) {
        createPerPeriodTimerNoLock(&data, periodMs);
    }

    const auto myIt = std::prev(data.callbacks.end());
    return myIt;
}

void PeriodicReporter::removeTask(System::Duration periodMs,
                                  CallbackList::iterator iter) {
    AutoLock lock(mLock);

    PerPeriodData& data = mPeriodDataByPeriod[periodMs];
    data.callbacks.erase(iter);
    if (data.callbacks.empty()) {
        data.task.clear();
    }
}

}  // namespace metrics
}  // namespace android
