#pragma once

#include <maps/wikimap/mapspro/services/mrc/libs/config/include/config.h>

#include <boost/filesystem.hpp>

#include <string>

namespace maps {
namespace mrc {
namespace unittest {

common::SharedXmlDoc readUnittestConfig();

// A wrapper intended to combine multiple test fixtures that modify and share
// the same config.
// It works in the following way.
// 1. An instance of UnittestConfig is created
// 2. This instance is copied to the private base of the wrapper and modified
//    by fixtures this wrapper consists of (not necessary in that order).
// 3. A common::Config instance which is read from the temporary config file
//    is cached in the config_ data member.
//
// WARNING: the order of base classes instantiation is not defined by the
// standard, so don't rely on it. I.e. you'll get into troubles if you try to
// pass the private UnittestConfig base to the base fixtures.
template <class... FTs>
class WithUnittestConfig : public FTs... {
public:
    // Each fixture must accept non-constant reference to xml3::Doc in
    // constructor and reset respective values.
    WithUnittestConfig(common::SharedXmlDoc doc = readUnittestConfig())
        : FTs(*doc)...
        , doc_(doc)
        // At this moment all base classes must have patched doc,
        // so it can be parsed.
        , config_(doc)
        , configPath_(boost::filesystem::unique_path())
    {
        std::ofstream file(configPath_.string());
        doc_->save(file);
    }

    ~WithUnittestConfig()
    {
        boost::filesystem::remove_all(configPath_);
    }

    const common::Config& config() const
    {
        return config_;
    }

    const boost::filesystem::path& configPath() const
    {
        return configPath_;
    }

private:
    common::SharedXmlDoc doc_;
    common::Config config_;
    boost::filesystem::path configPath_;
};

} // namespace unittest
} // namespace mrc
} // namespace maps
