/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 <gtest/gtest.h>
#include <algorithm>
#include <atomic>
#include <chrono>
#include <thread>
#include <vector>
#include "lib/Latch.h"
#include "lib/SynchronizedHashMap.h"

using namespace pulsar;
using SyncMapType = SynchronizedHashMap<int, int>;
using OptValue = typename SyncMapType::OptValue;
using PairVector = typename SyncMapType::PairVector;

inline void sleepMs(long millis) { std::this_thread::sleep_for(std::chrono::milliseconds(millis)); }

inline PairVector sort(PairVector pairs) {
    std::sort(pairs.begin(), pairs.end(), [](const std::pair<int, int>& lhs, const std::pair<int, int>& rhs) {
        return lhs.first < rhs.first;
    });
    return pairs;
}

TEST(SynchronizedHashMap, testClear) {
    SynchronizedHashMap<int, int> m({{1, 100}, {2, 200}});
    m.clear();
    ASSERT_EQ(m.toPairVector(), PairVector{});
}

TEST(SynchronizedHashMap, testRemoveAndFind) {
    SyncMapType m({{1, 100}, {2, 200}, {3, 300}});

    OptValue optValue;
    optValue = m.findFirstValueIf([](const int& x) { return x == 200; });
    ASSERT_TRUE(optValue.is_present());
    ASSERT_EQ(optValue.value(), 200);

    optValue = m.findFirstValueIf([](const int& x) { return x >= 301; });
    ASSERT_FALSE(optValue.is_present());

    optValue = m.find(1);
    ASSERT_TRUE(optValue.is_present());
    ASSERT_EQ(optValue.value(), 100);

    ASSERT_FALSE(m.find(0).is_present());
    ASSERT_FALSE(m.remove(0).is_present());

    optValue = m.remove(1);
    ASSERT_TRUE(optValue.is_present());
    ASSERT_EQ(optValue.value(), 100);

    ASSERT_FALSE(m.remove(1).is_present());
    ASSERT_FALSE(m.find(1).is_present());
}

TEST(SynchronizedHashMapTest, testForEach) {
    SyncMapType m({{1, 100}, {2, 200}, {3, 300}});
    std::vector<int> values;
    m.forEachValue([&values](const int& value) { values.emplace_back(value); });
    std::sort(values.begin(), values.end());
    ASSERT_EQ(values, std::vector<int>({100, 200, 300}));

    PairVector pairs;
    m.forEach([&pairs](const int& key, const int& value) { pairs.emplace_back(key, value); });
    PairVector expectedPairs({{1, 100}, {2, 200}, {3, 300}});
    ASSERT_EQ(sort(pairs), expectedPairs);
}

TEST(SynchronizedHashMap, testRecursiveMutex) {
    SyncMapType m({{1, 100}});
    OptValue optValue;
    m.forEach([&m, &optValue](const int& key, const int& value) {
        optValue = m.find(key);  // the internal mutex was locked again
    });
    ASSERT_TRUE(optValue.is_present());
    ASSERT_EQ(optValue.value(), 100);
}

TEST(SynchronizedHashMapTest, testThreadSafeForEach) {
    SyncMapType m({{1, 100}, {2, 200}, {3, 300}});

    Latch latch(1);
    std::thread t{[&m, &latch] {
        latch.wait();  // this thread must start after `m.forEach` started
        m.remove(2);
    }};

    std::atomic_bool firstElementDone{false};
    PairVector pairs;
    m.forEach([&latch, &firstElementDone, &pairs](const int& key, const int& value) {
        pairs.emplace_back(key, value);
        if (!firstElementDone) {
            latch.countdown();
            firstElementDone = true;
        }
        sleepMs(200);
    });
    {
        PairVector expectedPairs({{1, 100}, {2, 200}, {3, 300}});
        ASSERT_EQ(sort(pairs), expectedPairs);
    }
    t.join();
    {
        PairVector expectedPairs({{1, 100}, {3, 300}});
        ASSERT_EQ(sort(m.toPairVector()), expectedPairs);
    }
}
