/*Copyright (C) 2010-2023 Duncan Deveaux

This file is part of Hikou no mizu.

Hikou no mizu is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Hikou no mizu is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Hikou no mizu.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef DEF_CONF_WRITER
#define DEF_CONF_WRITER

#ifndef CONF_DISABLE_PLAYERKEYS
    class PlayerKeys;
#endif

#include "Tools/Log.hpp"
#include "Tools/Format.hpp"
#include <string>
#include <vector>
#include <sstream>

/// Class to write key/value configuration items to a file
class ConfWriter
{
    public:
        /// Adds a key/value configuration item with a std::string value
        void addItem(const std::string &name, const std::string &value);

        /// Adds a configuration item with a std::uint8_t value
        /// as an integer between 0 and 255, not as a character
        void addItem(const std::string &name, std::uint8_t value)
        {
            addItem(name, static_cast<int>(value));
        }

        /// Attempts to convert a value of type T to std::string and add it
        template <typename T>
        void addItem(const std::string &name, T value)
        {
            std::string valueString;
            if (!convertItem(value, valueString))
            {
                Log::err(Format::format("Could not write configuration item {} "
                                       "from type {}", name, typeid(T).name()));
                return;
            }

            addItem(name, valueString);
        }

        #ifndef CONF_DISABLE_PLAYERKEYS
            /// Utility method to add player keys as a
            /// set of configuration items
            void addPlayerKeysList(const PlayerKeys &value);
        #endif

        /// Writes the current set of configuration items to a file
        bool writeFile(const std::string &filePath) const;

    private:
        /// Attempts to convert an arbitrary type T to a std::string value
        template <typename T>
        bool convertItem(const T value, std::string &target) const
        {
            std::ostringstream convertToString;
            convertToString << value;

            if (!convertToString.fail())
            {
                target = convertToString.str();
                return true;
            }

            return false;
        }

        std::vector< std::pair<std::string, std::string> > m_confItems;
};

#endif
