#pragma once
#include "BaseStation.h"
#include "../Aircraft/Aircraft.h"
#include "../Aircraft/Flight_VTO.h"
#include "../External_Database/export.h"
#include <unordered_map>
#include <memory>
#include <vector>
#include <shared_mutex>
#include <functional>


template <
    typename Key_Type,
    typename Value_Type,
    size_t Shard_Count = 64
>
struct Data_Map {
    using Ptr = std::shared_ptr<Value_Type>;

    size_t size() const {
        size_t ret = 0;

        for (const auto& shard : shards) {
            std::shared_lock<std::shared_mutex> g(shard.mtx);
            ret += shard.map.size();
        }

        return ret;
    }

    Ptr get(const Key_Type& key) const {
        const auto& shard = get_shard(key);

        std::shared_lock<std::shared_mutex> g(shard.mtx);

        auto iter = shard.map.find(key);
        if (iter == shard.map.end()) {
            return nullptr;
        }

        return iter->second;
    }

    Ptr create(const Key_Type& key) {
        auto& shard = get_shard(key);

        {
            std::shared_lock<std::shared_mutex> g(shard.mtx);

            auto iter = shard.map.find(key);
            if (iter != shard.map.end()) {
                return iter->second;
            }
        }

        // 构造对象放锁外，避免构造期间占锁
        auto new_value = std::make_shared<Value_Type>(key);

        {
            std::unique_lock<std::shared_mutex> g(shard.mtx);

            auto [iter, inserted] = shard.map.emplace(key, new_value);

            // 如果别的线程已经创建了，返回已有对象
            return iter->second;
        }
    }

    void remove(const Key_Type& key) {
        auto& shard = get_shard(key);

        std::unique_lock<std::shared_mutex> g(shard.mtx);
        shard.map.erase(key);
    }

    std::vector<Ptr> values() const {
        std::vector<Ptr> ret;

        for (const auto& shard : shards) {
            std::shared_lock<std::shared_mutex> g(shard.mtx);

            for (const auto& [key, val] : shard.map) {
                ret.push_back(val);
            }
        }

        return ret;
    }

    template <typename Cond>
    std::vector<Ptr> get_cond(Cond&& cond) const {
        std::vector<Ptr> ret;

        for (const auto& shard : shards) {
            std::vector<Ptr> snapshot;

            {
                std::shared_lock<std::shared_mutex> g(shard.mtx);

                snapshot.reserve(shard.map.size());

                for (const auto& [key, val] : shard.map) {
                    snapshot.push_back(val);
                }
            }

            // cond 放锁外执行
            for (const auto& val : snapshot) {
                if (cond(val)) {
                    ret.push_back(val);
                }
            }
        }

        return ret;
    }

    template <typename Cond>
    void remove_cond(Cond&& cond) {
        for (auto& shard : shards) {
            std::vector<std::pair<Key_Type, Ptr>> snapshot;

            {
                std::shared_lock<std::shared_mutex> g(shard.mtx);

                snapshot.reserve(shard.map.size());

                for (const auto& [key, val] : shard.map) {
                    snapshot.emplace_back(key, val);
                }
            }

            std::vector<std::pair<Key_Type, Ptr>> need_remove;

            // cond 放锁外执行
            for (const auto& [key, val] : snapshot) {
                if (cond(val)) {
                    need_remove.emplace_back(key, val);
                }
            }

            if (need_remove.empty()) {
                continue;
            }

            {
                std::unique_lock<std::shared_mutex> g(shard.mtx);

                for (const auto& [key, old_val] : need_remove) {
                    auto iter = shard.map.find(key);
                    if (iter == shard.map.end()) {
                        continue;
                    }

                    // 防止同 key 已经被换成新对象，误删
                    if (iter->second == old_val) {
                        shard.map.erase(iter);
                    }
                }
            }
        }
    }

    void delete_all() {
        for (auto& shard : shards) {
            std::unique_lock<std::shared_mutex> g(shard.mtx);
            shard.map.clear();
        }
    }

protected:
    struct Shard {
        mutable std::shared_mutex mtx;
        std::unordered_map<Key_Type, Ptr> map;
    };

    Shard& get_shard(const Key_Type& key) {
        const size_t index = hasher(key) % Shard_Count;
        return shards[index];
    }

    const Shard& get_shard(const Key_Type& key) const {
        const size_t index = hasher(key) % Shard_Count;
        return shards[index];
    }

protected:
    std::hash<Key_Type> hasher;
    Shard shards[Shard_Count];
};


class DataBase : public SSR::Data_Source_Interface {
public:
    std::shared_ptr<SSR::Aircraft_Info> get_aircraft(const std::string& icao) override;
    std::shared_ptr<SSR::Aircraft_Info> create_aircraft(const std::string& icao) override;
    Psc::JSON get_aircraftlist();
    Psc::JSON get_aircraftlist(int limit_msg_num);
    BaseStation base_station;
    void delete_timeout_aircraft();
    std::string get_key() override {
        return key;
    }
    std::string key;
    std::atomic<size_t> have_pos_aircraft_num{};
    Psc::JSON get_all_aircraft_json();
    Psc::JSON get_aircraft_list_after(time_t timestamp);
#ifdef Cache_Some_Mode_S
    Psc::JSON get_limit_mode_s_msg_info();
#endif
    size_t get_aircraft_num();
    void clear_aircraft() { aircraft_map.delete_all(); }
    ~DataBase() override {
        aircraft_map.delete_all();
    }

protected:


    Data_Map<std::string, Aircraft> aircraft_map;
};


struct Mode_S_Msg;
void database_server(Global* g);

