#pragma once

#include <xrpld/app/rdb/PeerFinder.h>
#include <xrpld/peerfinder/detail/Store.h>

#include <xrpl/rdb/SociDB.h>

namespace xrpl {
namespace PeerFinder {

/** Database persistence for PeerFinder using SQLite */
class StoreSqdb : public Store
{
private:
    beast::Journal m_journal;
    soci::session m_sqlDb;

public:
    enum {
        // This determines the on-database format of the data
        currentSchemaVersion = 4
    };

    explicit StoreSqdb(beast::Journal journal = beast::Journal{beast::Journal::getNullSink()})
        : m_journal(journal)
    {
    }

    ~StoreSqdb()
    {
    }

    void
    open(BasicConfig const& config)
    {
        init(config);
        update();
    }

    // Loads the bootstrap cache, calling the callback for each entry
    //
    std::size_t
    load(load_callback const& cb) override
    {
        std::size_t n(0);

        readPeerFinderDB(m_sqlDb, [&](std::string const& s, int valence) {
            beast::IP::Endpoint const endpoint(beast::IP::Endpoint::from_string(s));

            if (!is_unspecified(endpoint))
            {
                cb(endpoint, valence);
                ++n;
            }
            else
            {
                JLOG(m_journal.error()) << "Bad address string '" << s << "' in Bootcache table";
            }
        });

        return n;
    }

    // Overwrites the stored bootstrap cache with the specified array.
    //
    void
    save(std::vector<Entry> const& v) override
    {
        savePeerFinderDB(m_sqlDb, v);
    }

    // Convert any existing entries from an older schema to the
    // current one, if appropriate.
    void
    update()
    {
        updatePeerFinderDB(m_sqlDb, currentSchemaVersion, m_journal);
    }

private:
    void
    init(BasicConfig const& config)
    {
        initPeerFinderDB(m_sqlDb, config, m_journal);
    }
};

}  // namespace PeerFinder
}  // namespace xrpl
