/*
 * Copyright (C) 2019 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 <any>
#include <map>
#include <sstream>
#include <string>
#include <variant>
#include <vector>

#include <android-base/thread_annotations.h>
#include <media/MediaMetricsItem.h>
#include <utils/Timers.h>

namespace android::mediametrics {

// define a way of printing the monostate
inline std::ostream & operator<< (std::ostream& s,
                           std::monostate const& v __unused) {
    s << "none_item";
    return s;
}

// define a way of printing a std::pair.
template <typename T, typename U>
std::ostream & operator<< (std::ostream& s,
                           const std::pair<T, U>& v) {
    s << "{ " << v.first << ", " << v.second << " }";
    return s;
}

// define a way of printing a variant
// see https://en.cppreference.com/w/cpp/utility/variant/visit
template <typename T0, typename ... Ts>
std::ostream & operator<< (std::ostream& s,
                           std::variant<T0, Ts...> const& v) {
    std::visit([&s](auto && arg){ s << std::forward<decltype(arg)>(arg); }, v);
    return s;
}

/**
 * The TimeMachine is used to record timing changes of MediaAnalyticItem
 * properties.
 *
 * Any URL that ends with '#' (AMEDIAMETRICS_PROP_SUFFIX_CHAR_DUPLICATES_ALLOWED)
 * will have a time sequence that keeps duplicates.
 *
 * The TimeMachine is NOT thread safe.
 */
class TimeMachine final { // made final as we have copy constructor instead of dup() override.
public:
    using Elem = Item::Prop::Elem;  // use the Item property element.
    using PropertyHistory = std::multimap<int64_t /* time */, Elem>;

private:

    // KeyHistory contains no lock.
    // Access is through the TimeMachine, and a hash-striped lock is used
    // before calling into KeyHistory.
    class KeyHistory  {
    public:
        template <typename T>
        KeyHistory(T key, uid_t allowUid, int64_t time)
            : mKey(key)
            , mAllowUid(allowUid)
            , mCreationTime(time)
            , mLastModificationTime(time)
        {
            // allowUid allows an untrusted client with a matching uid to set properties
            // in this key.
            // If allowUid == (uid_t)-1, no untrusted client may set properties in the key.
            if (allowUid != (uid_t)-1) {
                // Set ALLOWUID property here; does not change after key creation.
                putValue(AMEDIAMETRICS_PROP_ALLOWUID, (int32_t)allowUid, time);
            }
        }

        KeyHistory(const KeyHistory &other) = default;

        // Return NO_ERROR only if the passed in uidCheck is -1 or matches
        // the internal mAllowUid.
        // An external submit will always have a valid uidCheck parameter.
        // An internal get request within mediametrics will have a uidCheck == -1 which
        // we allow to proceed.
        status_t checkPermission(uid_t uidCheck) const {
            return uidCheck != (uid_t)-1 && uidCheck != mAllowUid ? PERMISSION_DENIED : NO_ERROR;
        }

        template <typename T>
        status_t getValue(const std::string &property, T* value, int64_t time = 0) const
                REQUIRES(mPseudoKeyHistoryLock) {
            if (time == 0) time = systemTime(SYSTEM_TIME_REALTIME);
            const auto tsptr = mPropertyMap.find(property);
            if (tsptr == mPropertyMap.end()) return BAD_VALUE;
            const auto& timeSequence = tsptr->second;
            auto eptr = timeSequence.upper_bound(time);
            if (eptr == timeSequence.begin()) return BAD_VALUE;
            --eptr;
            if (eptr == timeSequence.end()) return BAD_VALUE;
            const T* vptr = std::get_if<T>(&eptr->second);
            if (vptr == nullptr) return BAD_VALUE;
            *value = *vptr;
            return NO_ERROR;
        }

        template <typename T>
        status_t getValue(const std::string &property, T defaultValue, int64_t time = 0) const
                REQUIRES(mPseudoKeyHistoryLock){
            T value;
            return getValue(property, &value, time) != NO_ERROR ? defaultValue : value;
        }

        void putProp(
                const std::string &name, const mediametrics::Item::Prop &prop, int64_t time = 0)
                REQUIRES(mPseudoKeyHistoryLock) {
            //alternatively: prop.visit([&](auto value) { putValue(name, value, time); });
            putValue(name, prop.get(), time);
        }

        template <typename T>
        void putValue(const std::string &property, T&& e, int64_t time = 0)
                REQUIRES(mPseudoKeyHistoryLock) {
            if (time == 0) time = systemTime(SYSTEM_TIME_REALTIME);
            mLastModificationTime = time;
            if (mPropertyMap.size() >= kKeyMaxProperties &&
                    !mPropertyMap.count(property)) {
                ALOGV("%s: too many properties, rejecting %s", __func__, property.c_str());
                return;
            }
            auto& timeSequence = mPropertyMap[property];
            Elem el{std::forward<T>(e)};
            if (timeSequence.empty()           // no elements
                    || property.back() == AMEDIAMETRICS_PROP_SUFFIX_CHAR_DUPLICATES_ALLOWED
                    || timeSequence.rbegin()->second != el) { // value changed
                timeSequence.emplace_hint(timeSequence.end(), time, std::move(el));

                if (timeSequence.size() > kTimeSequenceMaxElements) {
                    ALOGV("%s: restricting maximum elements (discarding oldest) for %s",
                            __func__, property.c_str());
                    timeSequence.erase(timeSequence.begin());
                }
            }
        }

        std::pair<std::string, int32_t> dump(int32_t lines, int64_t time) const
                REQUIRES(mPseudoKeyHistoryLock) {
            std::stringstream ss;
            int32_t ll = lines;
            for (auto& tsPair : mPropertyMap) {
                if (ll <= 0) break;
                std::string s = dump(mKey, tsPair, time);
                if (s.size() > 0) {
                    --ll;
                    ss << s;
                }
            }
            return { ss.str(), lines - ll };
        }

        int64_t getLastModificationTime() const REQUIRES(mPseudoKeyHistoryLock) {
            return mLastModificationTime;
        }

    private:
        static std::string dump(
                const std::string &key,
                const std::pair<std::string /* prop */, PropertyHistory>& tsPair,
                int64_t time) {
            const auto timeSequence = tsPair.second;
            auto eptr = timeSequence.lower_bound(time);
            if (eptr == timeSequence.end()) {
                return {}; // don't dump anything. tsPair.first + "={};\n";
            }
            std::stringstream ss;
            ss << key << "." << tsPair.first << "={";

            time_string_t last_timestring{}; // last timestring used.
            while (true) {
                const time_string_t timestring = mediametrics::timeStringFromNs(eptr->first);
                // find common prefix offset.
                const size_t offset = commonTimePrefixPosition(timestring.time,
                        last_timestring.time);
                last_timestring = timestring;
                ss << "(" << (offset == 0 ? "" : "~") << &timestring.time[offset]
                    << ") " << eptr->second;
                if (++eptr == timeSequence.end()) {
                    break;
                }
                ss << ", ";
            }
            ss << "};\n";
            return ss.str();
        }

        const std::string mKey;
        const uid_t mAllowUid;
        const int64_t mCreationTime __unused;

        int64_t mLastModificationTime;
        std::map<std::string /* property */, PropertyHistory> mPropertyMap;
    };

    using History = std::map<std::string /* key */, std::shared_ptr<KeyHistory>>;

    static inline constexpr size_t kTimeSequenceMaxElements = 100;
    static inline constexpr size_t kKeyMaxProperties = 100;
    static inline constexpr size_t kKeyLowWaterMark = 500;
    static inline constexpr size_t kKeyHighWaterMark = 1000;

    // Estimated max data space usage is 3KB * kKeyHighWaterMark.

public:

    TimeMachine() = default;
    TimeMachine(size_t keyLowWaterMark, size_t keyHighWaterMark)
        : mKeyLowWaterMark(keyLowWaterMark)
        , mKeyHighWaterMark(keyHighWaterMark) {
        LOG_ALWAYS_FATAL_IF(keyHighWaterMark <= keyLowWaterMark,
              "%s: required that keyHighWaterMark:%zu > keyLowWaterMark:%zu",
                  __func__, keyHighWaterMark, keyLowWaterMark);
    }

    // The TimeMachine copy constructor/assignment uses a deep copy,
    // though the snapshot is not instantaneous nor isochronous.
    //
    // If there are concurrent operations ongoing in the other TimeMachine
    // then there may be some history more recent than others (a time shear).
    // This is expected to be a benign addition in history as small number of
    // future elements are incorporated.
    TimeMachine(const TimeMachine& other) {
        *this = other;
    }
    TimeMachine& operator=(const TimeMachine& other) {
        std::lock_guard lock(mLock);
        mHistory.clear();

        {
            std::lock_guard lock2(other.mLock);
            mHistory = other.mHistory;
        }

        // Now that we safely have our own shared pointers, let's dup them
        // to ensure they are decoupled.  We do this by acquiring the other lock.
        for (const auto &[lkey, lhist] : mHistory) {
            std::lock_guard lock2(other.getLockForKey(lkey));
            mHistory[lkey] = std::make_shared<KeyHistory>(*lhist);
        }
        return *this;
    }

    /**
     * Put all the properties from an item into the Time Machine log.
     */
    status_t put(const std::shared_ptr<const mediametrics::Item>& item, bool isTrusted = false) {
        const int64_t time = item->getTimestamp();
        const std::string &key = item->getKey();

        ALOGV("%s(%zu, %zu): key: %s  isTrusted:%d  size:%zu",
                __func__, mKeyLowWaterMark, mKeyHighWaterMark,
                key.c_str(), (int)isTrusted, item->count());
        std::shared_ptr<KeyHistory> keyHistory;
        {
            std::vector<std::any> garbage;
            std::lock_guard lock(mLock);

            auto it = mHistory.find(key);
            if (it == mHistory.end()) {
                if (!isTrusted) return PERMISSION_DENIED;

                (void)gc(garbage);

                // We set the allowUid for client access on key creation.
                int32_t allowUid = -1;
                (void)item->get(AMEDIAMETRICS_PROP_ALLOWUID, &allowUid);
                // no keylock needed here as we are sole owner
                // until placed on mHistory.
                keyHistory = std::make_shared<KeyHistory>(
                    key, allowUid, time);
                mHistory[key] = keyHistory;
            } else {
                keyHistory = it->second;
            }
        }

        // deferred contains remote properties (for other keys) to do later.
        std::vector<const mediametrics::Item::Prop *> deferred;
        {
            // handle local properties
            std::lock_guard lock(getLockForKey(key));
            if (!isTrusted) {
                status_t status = keyHistory->checkPermission(item->getUid());
                if (status != NO_ERROR) return status;
            }

            for (const auto &prop : *item) {
                const std::string &name = prop.getName();
                if (name.size() == 0 || name[0] == '_') continue;

                // Cross key settings are with [key]property
                if (name[0] == '[') {
                    if (!isTrusted) continue;
                    deferred.push_back(&prop);
                } else {
                    keyHistory->putProp(name, prop, time);
                }
            }
        }

        // handle remote properties, if any
        for (const auto propptr : deferred) {
            const auto &prop = *propptr;
            const std::string &name = prop.getName();
            size_t end = name.find_first_of(']'); // TODO: handle nested [] or escape?
            if (end == 0) continue;
            std::string remoteKey = name.substr(1, end - 1);
            std::string remoteName = name.substr(end + 1);
            if (remoteKey.size() == 0 || remoteName.size() == 0) continue;
            std::shared_ptr<KeyHistory> remoteKeyHistory;
            {
                std::lock_guard lock(mLock);
                auto it = mHistory.find(remoteKey);
                if (it == mHistory.end()) continue;
                remoteKeyHistory = it->second;
            }
            std::lock_guard lock(getLockForKey(remoteKey));
            remoteKeyHistory->putProp(remoteName, prop, time);
        }
        return NO_ERROR;
    }

    template <typename T>
    status_t get(const std::string &key, const std::string &property,
            T* value, int32_t uidCheck = -1, int64_t time = 0) const {
        std::shared_ptr<KeyHistory> keyHistory;
        {
            std::lock_guard lock(mLock);
            const auto it = mHistory.find(key);
            if (it == mHistory.end()) return BAD_VALUE;
            keyHistory = it->second;
        }
        std::lock_guard lock(getLockForKey(key));
        return keyHistory->checkPermission(uidCheck)
                ?: keyHistory->getValue(property, value, time);
    }

    /**
     * Individual property put.
     *
     * Put takes in a time (if none is provided then SYSTEM_TIME_REALTIME is used).
     */
    template <typename T>
    status_t put(const std::string &url, T &&e, int64_t time = 0) {
        std::string key;
        std::string prop;
        std::shared_ptr<KeyHistory> keyHistory =
            getKeyHistoryFromUrl(url, &key, &prop);
        if (keyHistory == nullptr) return BAD_VALUE;
        if (time == 0) time = systemTime(SYSTEM_TIME_REALTIME);
        std::lock_guard lock(getLockForKey(key));
        keyHistory->putValue(prop, std::forward<T>(e), time);
        return NO_ERROR;
    }

    /**
     * Individual property get
     */
    template <typename T>
    status_t get(const std::string &url, T* value, int32_t uidCheck, int64_t time = 0) const {
        std::string key;
        std::string prop;
        std::shared_ptr<KeyHistory> keyHistory =
            getKeyHistoryFromUrl(url, &key, &prop);
        if (keyHistory == nullptr) return BAD_VALUE;

        std::lock_guard lock(getLockForKey(key));
        return keyHistory->checkPermission(uidCheck)
               ?: keyHistory->getValue(prop, value, time);
    }

    /**
     * Individual property get with default
     */
    template <typename T>
    T get(const std::string &url, const T &defaultValue, int32_t uidCheck,
            int64_t time = 0) const {
        T value;
        return get(url, &value, uidCheck, time) == NO_ERROR
                ? value : defaultValue;
    }

    /**
     *  Returns number of keys in the Time Machine.
     */
    size_t size() const {
        std::lock_guard lock(mLock);
        return mHistory.size();
    }

    /**
     * Clears all properties from the Time Machine.
     */
    void clear() {
        std::lock_guard lock(mLock);
        mHistory.clear();
    }

    /**
     * Returns a pair consisting of the TimeMachine state as a string
     * and the number of lines in the string.
     *
     * The number of lines in the returned pair is used as an optimization
     * for subsequent line limiting.
     *
     * \param lines the maximum number of lines in the string returned.
     * \param key selects only that key.
     * \param sinceNs the nanoseconds since Unix epoch to start dump (0 shows all)
     * \param prefix the desired key prefix to match (nullptr shows all)
     */
    std::pair<std::string, int32_t> dump(
            int32_t lines = INT32_MAX, int64_t sinceNs = 0, const char *prefix = nullptr) const {
        std::lock_guard lock(mLock);
        std::stringstream ss;
        int32_t ll = lines;

        for (auto it = prefix != nullptr ? mHistory.lower_bound(prefix) : mHistory.begin();
                it != mHistory.end();
                ++it) {
            if (ll <= 0) break;
            if (prefix != nullptr && !startsWith(it->first, prefix)) break;
            std::lock_guard lock(getLockForKey(it->first));
            auto [s, l] = it->second->dump(ll, sinceNs);
            ss << s;
            ll -= l;
        }
        return { ss.str(), lines - ll };
    }

private:

    // Obtains the lock for a KeyHistory.
    std::mutex &getLockForKey(const std::string &key) const
            RETURN_CAPABILITY(mPseudoKeyHistoryLock) {
        return mKeyLocks[std::hash<std::string>{}(key) % std::size(mKeyLocks)];
    }

    // Finds a KeyHistory from a URL.  Returns nullptr if not found.
    std::shared_ptr<KeyHistory> getKeyHistoryFromUrl(
            const std::string& url, std::string* key, std::string *prop) const {
        std::lock_guard lock(mLock);

        auto it = mHistory.upper_bound(url);
        if (it == mHistory.begin()) {
           return nullptr;
        }
        --it;  // go to the actual key, if it exists.

        const std::string& itKey = it->first;
        if (strncmp(itKey.c_str(), url.c_str(), itKey.size())) {
            return nullptr;
        }
        if (key) *key = itKey;
        if (prop) *prop = url.substr(itKey.size() + 1);
        return it->second;
    }

    /**
     * Garbage collects if the TimeMachine size exceeds the high water mark.
     *
     * This GC operation limits the number of keys stored (not the size of properties
     * stored in each key).
     *
     * \param garbage a type-erased vector of elements to be destroyed
     *        outside of lock.  Move large items to be destroyed here.
     *
     * \return true if garbage collection was done.
     */
    bool gc(std::vector<std::any>& garbage) REQUIRES(mLock) {
        // TODO: something better than this for garbage collection.
        if (mHistory.size() < mKeyHighWaterMark) return false;

        ALOGD("%s: garbage collection", __func__);

        // erase everything explicitly expired.
        std::multimap<int64_t, std::string> accessList;
        // use a stale vector with precise type to avoid type erasure overhead in garbage
        std::vector<std::shared_ptr<KeyHistory>> stale;

        for (auto it = mHistory.begin(); it != mHistory.end();) {
            const std::string& key = it->first;
            std::shared_ptr<KeyHistory> &keyHist = it->second;

            std::lock_guard lock(getLockForKey(it->first));
            int64_t expireTime = keyHist->getValue("_expire", -1 /* default */);
            if (expireTime != -1) {
                stale.emplace_back(std::move(it->second));
                it = mHistory.erase(it);
            } else {
                accessList.emplace(keyHist->getLastModificationTime(), key);
                ++it;
            }
        }

        if (mHistory.size() > mKeyLowWaterMark) {
           const size_t toDelete = mHistory.size() - mKeyLowWaterMark;
           auto it = accessList.begin();
           for (size_t i = 0; i < toDelete; ++i) {
               auto it2 = mHistory.find(it->second);
               stale.emplace_back(std::move(it2->second));
               mHistory.erase(it2);
               ++it;
           }
        }
        garbage.emplace_back(std::move(accessList));
        garbage.emplace_back(std::move(stale));

        ALOGD("%s(%zu, %zu): key size:%zu",
                __func__, mKeyLowWaterMark, mKeyHighWaterMark,
                mHistory.size());
        return true;
    }

    const size_t mKeyLowWaterMark = kKeyLowWaterMark;
    const size_t mKeyHighWaterMark = kKeyHighWaterMark;

    /**
     * Locking Strategy
     *
     * Each key in the History has a KeyHistory. To get a shared pointer to
     * the KeyHistory requires a lookup of mHistory under mLock.  Once the shared
     * pointer to KeyHistory is obtained, the mLock for mHistory can be released.
     *
     * Once the shared pointer to the key's KeyHistory is obtained, the KeyHistory
     * can be locked for read and modification through the method getLockForKey().
     *
     * Instead of having a mutex per KeyHistory, we use a hash striped lock
     * which assigns a mutex based on the hash of the key string.
     *
     * Once the last shared pointer reference to KeyHistory is released, it is
     * destroyed.  This is done through the garbage collection method.
     *
     * This two level locking allows multiple threads to access the TimeMachine
     * in parallel.
     */

    mutable std::mutex mLock;           // Lock for mHistory
    History mHistory GUARDED_BY(mLock);

    // KEY_LOCKS is the number of mutexes for keys.
    // It need not be a power of 2, but faster that way.
    static inline constexpr size_t KEY_LOCKS = 256;
    mutable std::mutex mKeyLocks[KEY_LOCKS];  // Hash-striped lock for KeyHistory based on key.

    // Used for thread-safety analysis, we create a fake mutex object to represent
    // the hash stripe lock mechanism, which is then tracked by the compiler.
    class CAPABILITY("mutex") PseudoLock {};
    static inline PseudoLock mPseudoKeyHistoryLock;
};

} // namespace android::mediametrics
