#ifndef TILE_BASE_CONFIG_LAYERED_CONFIGURATION_H
#define TILE_BASE_CONFIG_LAYERED_CONFIGURATION_H

#pragma once

#include "tile/base/config/configuration.h"
#include <list>

namespace tile {
class LayeredConfiguration : public Configuration {
public:
    using Ptr = RefPtr<LayeredConfiguration>;
    LayeredConfiguration();
    LayeredConfiguration(const LayeredConfiguration &)            = delete;
    LayeredConfiguration &operator=(const LayeredConfiguration &) = delete;

    void Add(Configuration::Ptr cfg);
    void Add(Configuration::Ptr cfg, int priority);
    void Add(Configuration::Ptr cfg, const std::string &label);
    void Add(Configuration::Ptr cfg, const std::string &label, int priority);
    void Add(Configuration::Ptr cfg, const std::string &label, bool writeable);
    void Add(Configuration::Ptr cfg, const std::string &label, int priority, bool writeable);
    void Add(Configuration::Ptr cfg, int priority, bool writeable);
    void AddWriteable(Configuration::Ptr cfg, int priority);
    Configuration::Ptr Find(const Slice &label) const;
    void RemoveConfig(Configuration::Ptr cfg);

protected:
    struct ConfigItem {
        Configuration::Ptr cfg;
        // ... > -2 > -1 > 0 > 1 > 2 > 3 > 4 ...
        int priority;
        // can remove or set new?
        bool writeable;
        std::string label;
    };

    bool GetRaw(const Slice &key, std::string *value) const override;
    bool SetRaw(const Slice &key, const Slice &value) override;
    Configuration::Keys Enumerate(const Slice &key) const override;
    void RemoveRaw(const std::string &key);

    int lowest() const;
    int highest() const;

    ~LayeredConfiguration();

private:
    using ConfigList = std::list<ConfigItem>;
    ConfigList configs_;
};
}// namespace tile

#endif// TILE_BASE_CONFIG_LAYERED_CONFIGURATION_H
