#ifndef RUNTIME_STATE_CACHE_HPP_
#define RUNTIME_STATE_CACHE_HPP_

#include <Utilities/Utilities.hpp>
#include <memory>
#include <string>
#include <unordered_map>
#include <any>

/**
 * @brief A cache which maps URLs to arbitrary runtime states.
 *
 * This is used for example by GUIs to retain their state after being closed.
 */
class RuntimeStateCache
{
private:
    static std::unordered_map<std::string, std::any> cache;

public:
    /**
     * @brief Get the state at the specified URL.
     * 
     * If the state does not yet exist, it is created using the default constructor. If you
     * call this method with different types on the same URL, it causes a crash.
     *
     * If `url` is an empty string, then a new `TState` is returned without being cached.
     */
    template<typename TState>
    static std::shared_ptr<TState> get(const std::string &url)
    {
        if (url.empty())
        {
            return std::make_shared<TState>();
        }

        if (cache.contains(url))
        {
            return std::any_cast<std::shared_ptr<TState>>(cache[url]);
        }

        std::shared_ptr<TState> newState = std::make_shared<TState>();
        cache[url] = newState;
        return newState;
    }
};

#endif