// Copyright 2017 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.

#pragma once

#include <string>
#include <type_traits>

namespace Config {
namespace detail {
// std::underlying_type may only be used with enum types, so make sure T is an enum type first.
template <typename T>
using UnderlyingType = typename std::enable_if_t<std::is_enum<T>{}, std::underlying_type<T>>::type;
} // namespace detail

struct ConfigLocation {
    std::string section;
    std::string key;

    bool operator==(const ConfigLocation& other) const;
    bool operator!=(const ConfigLocation& other) const;
    bool operator<(const ConfigLocation& other) const;
};

template <typename T>
struct ConfigInfo {
    ConfigInfo(const ConfigLocation& location_, const T& default_value_)
        : location{location_}, default_value{default_value_} {}

    // Make it easy to convert ConfigInfo<Enum> into ConfigInfo<UnderlyingType<Enum>>
    // so that enum settings can still easily work with code that doesn't care about the enum
    // values.
    template <typename Enum,
              std::enable_if_t<std::is_same<T, detail::UnderlyingType<Enum>>::value>* = nullptr>
    ConfigInfo(const ConfigInfo<Enum>& other)
        : location{other.location}, default_value{static_cast<detail::UnderlyingType<Enum>>(
                                        other.default_value)} {}

    ConfigLocation location;
    T default_value;
};
} // namespace Config
