/*
 * Copyright (C) 2017 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.
 */

#pragma once

#include <aidl/android/os/IPullAtomCallback.h>
#include <aidl/android/os/IStatsCompanionService.h>
#include <utils/RefBase.h>

#include <list>
#include <vector>

#include "PullDataReceiver.h"
#include "PullUidProvider.h"
#include "StatsPuller.h"
#include "guardrail/StatsdStats.h"
#include "logd/LogEvent.h"
#include "packages/UidMap.h"

using aidl::android::os::IPullAtomCallback;
using aidl::android::os::IStatsCompanionService;
using std::shared_ptr;

namespace android {
namespace os {
namespace statsd {

typedef struct PullerKey {
    // The uid of the process that registers this puller.
    const int uid = -1;
    // The atom that this puller is for.
    const int atomTag;

    bool operator<(const PullerKey& that) const {
        if (uid < that.uid) {
            return true;
        }
        if (uid > that.uid) {
            return false;
        }
        return atomTag < that.atomTag;
    };

    bool operator==(const PullerKey& that) const {
        return uid == that.uid && atomTag == that.atomTag;
    };
} PullerKey;

class StatsPullerManager : public virtual RefBase {
public:
    StatsPullerManager();

    virtual ~StatsPullerManager() {
    }


    // Registers a receiver for tagId. It will be pulled on the nextPullTimeNs
    // and then every intervalNs thereafter.
    virtual void RegisterReceiver(int tagId, const ConfigKey& configKey,
                                  wp<PullDataReceiver> receiver, int64_t nextPullTimeNs,
                                  int64_t intervalNs);

    // Stop listening on a tagId.
    virtual void UnRegisterReceiver(int tagId, const ConfigKey& configKey,
                                    wp<PullDataReceiver> receiver);

    // Registers a pull uid provider for the config key. When pulling atoms, it will be used to
    // determine which uids to pull from.
    virtual void RegisterPullUidProvider(const ConfigKey& configKey, wp<PullUidProvider> provider);

    // Unregister a pull uid provider.
    virtual void UnregisterPullUidProvider(const ConfigKey& configKey,
                                           wp<PullUidProvider> provider);

    // Verify if we know how to pull for this matcher
    bool PullerForMatcherExists(int tagId) const;

    void OnAlarmFired(int64_t elapsedTimeNs);

    // Pulls the most recent data.
    // The data may be served from cache if consecutive pulls come within
    // mCoolDownNs.
    // Returns true if the pull was successful.
    // Returns false when
    //   1) the pull fails
    //   2) pull takes longer than mPullTimeoutNs (intrinsic to puller)
    //   3) Either a PullUidProvider was not registered for the config, or the there was no puller
    //      registered for any of the uids for this atom.
    // If the metric wants to make any change to the data, like timestamps, they
    // should make a copy as this data may be shared with multiple metrics.
    virtual bool Pull(int tagId, const ConfigKey& configKey, const int64_t eventTimeNs,
                      vector<std::shared_ptr<LogEvent>>* data);

    // Same as above, but directly specify the allowed uids to pull from.
    virtual bool Pull(int tagId, const vector<int32_t>& uids, const int64_t eventTimeNs,
                      vector<std::shared_ptr<LogEvent>>* data);

    // Clear pull data cache immediately.
    int ForceClearPullerCache();

    // Clear pull data cache if it is beyond respective cool down time.
    int ClearPullerCacheIfNecessary(int64_t timestampNs);

    void SetStatsCompanionService(shared_ptr<IStatsCompanionService> statsCompanionService);

    void RegisterPullAtomCallback(const int uid, const int32_t atomTag, const int64_t coolDownNs,
                                  const int64_t timeoutNs, const vector<int32_t>& additiveFields,
                                  const shared_ptr<IPullAtomCallback>& callback);

    void UnregisterPullAtomCallback(const int uid, const int32_t atomTag);

    std::map<const PullerKey, sp<StatsPuller>> kAllPullAtomInfo;

private:
    const static int64_t kMinCoolDownNs = NS_PER_SEC;
    const static int64_t kMaxTimeoutNs = 10 * NS_PER_SEC;
    shared_ptr<IStatsCompanionService> mStatsCompanionService = nullptr;

    // A struct containing an atom id and a Config Key
    typedef struct ReceiverKey {
        const int atomTag;
        const ConfigKey configKey;

        inline bool operator<(const ReceiverKey& that) const {
            return atomTag == that.atomTag ? configKey < that.configKey : atomTag < that.atomTag;
        }
    } ReceiverKey;

    typedef struct {
        int64_t nextPullTimeNs;
        int64_t intervalNs;
        wp<PullDataReceiver> receiver;
    } ReceiverInfo;

    // mapping from Receiver Key to receivers
    std::map<ReceiverKey, std::list<ReceiverInfo>> mReceivers;

    // mapping from Config Key to the PullUidProvider for that config
    std::map<ConfigKey, wp<PullUidProvider>> mPullUidProviders;

    bool PullLocked(int tagId, const ConfigKey& configKey, const int64_t eventTimeNs,
                    vector<std::shared_ptr<LogEvent>>* data);

    bool PullLocked(int tagId, const vector<int32_t>& uids, const int64_t eventTimeNs,
                    vector<std::shared_ptr<LogEvent>>* data);

    // locks for data receiver and StatsCompanionService changes
    std::mutex mLock;

    void updateAlarmLocked();

    int64_t mNextPullTimeNs;

    // Death recipient that is triggered when the process holding the IPullAtomCallback has died.
    ::ndk::ScopedAIBinder_DeathRecipient mPullAtomCallbackDeathRecipient;

    /**
     * Death recipient callback that is called when a pull atom callback dies.
     * The cookie is a pointer to a PullAtomCallbackDeathCookie.
     */
    static void pullAtomCallbackDied(void* cookie);

    FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvents);
    FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvent_LateAlarm);
    FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEventsWithActivation);
    FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEventsNoCondition);
    FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents);
    FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm);
    FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_WithActivation);

    FRIEND_TEST(StatsLogProcessorTest, TestPullUidProviderSetOnConfigUpdate);

    FRIEND_TEST(ConfigUpdateE2eTest, TestGaugeMetric);
    FRIEND_TEST(ConfigUpdateE2eTest, TestValueMetric);
};

}  // namespace statsd
}  // namespace os
}  // namespace android
