## This file is a template.  The comment below is emitted
## into the rendered file; feel free to edit this file.
// WARNING: Generated header. Do not edit!
<%
import re
from collections import defaultdict
from sdbusplus.namedelement import NamedElement
objects = settingsDict.keys()
sdbusplus_includes = []
props = defaultdict(list)
validators = defaultdict(tuple)

def get_setting_sdbusplus_type(setting_intf):
    setting = "sdbusplus::" + setting_intf.replace('.', '::')
    i = setting.rfind('::')
    setting = setting[:i] + '::server::' + setting[i+2:]
    return setting

def get_setting_type(path):
    path = path[1:]
    path = path.replace('/', '::')
    return path

def get_default_value(object, interface, prop):
    default_value = None
    for item in settingsDict[object]:
        if item['Interface'] == interface:
            default_value = item['Properties'][prop]['Default']
            break

    if isinstance(default_value, str) and  not \
        default_value.startswith('"') and '::' in default_value:
            ns = get_setting_sdbusplus_type(interface)
            i = ns.rfind('::')
            default_value = "{}::{}".format(ns[:i], default_value)

    return default_value
%>\
#pragma once

% for object in objects:
    % for item in settingsDict[object]:
<%
    include = item['Interface']
    include = include.replace('.', '/')
    include = include + "/server.hpp"
    sdbusplus_includes.append(include)
%>\
    % endfor
% endfor
#include <cereal/archives/json.hpp>
#include <cereal/types/vector.hpp>
#include <fstream>
#include <utility>
#include <filesystem>
#include <regex>
#include <phosphor-logging/elog.hpp>
#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/log.hpp>
#include <phosphor-logging/lg2.hpp>
#include <xyz/openbmc_project/Common/error.hpp>
using namespace phosphor::logging;

/* The DBus busname to own */
#define SETTINGS_BUSNAME "xyz.openbmc_project.Settings"
/* Path of directory housing persisted settings */
#define SETTINGS_PERSIST_PATH "/var/lib/phosphor-settings-manager/settings"

/* Class version to register with Cereal */
static constexpr size_t CLASS_VERSION = 2;
static constexpr size_t CLASS_VERSION_WITH_NVP = 2;

% for i in set(sdbusplus_includes):
#include "${i}"
% endfor

namespace phosphor
{
namespace settings
{

namespace fs = std::filesystem;

namespace persistent
{

// A setting d-bus object /foo/bar/baz is persisted in the filesystem with the
// same path. This eases re-construction of settings objects when we restore
// from the filesystem. This can be a problem though when you have two objects
// such as - /foo/bar and /foo/bar/baz. This is because 'bar' will be treated as
// a file in the first case, and a subdir in the second. To solve this, suffix
// files with a trailing __. The __ is a safe character sequence to use, because
// we won't have d-bus object paths ending with this.
// With this the objects would be persisted as - /foo/bar__ and /foo/bar/baz__.
constexpr auto fileSuffix = "__";

}

static fs::path getFilePath(const fs::path& objectPath)
{
    fs::path p(SETTINGS_PERSIST_PATH);
    p /= objectPath.relative_path();
    p += persistent::fileSuffix;
    return p;
}

% for object in objects:
<%
   ns = object.split('/')
   ns.pop(0)
%>\
% for n in ns:
namespace ${n}
{
% endfor
<%
    interfaces = []
    aliases = []
    for item in settingsDict[object]:
        interfaces.append(item['Interface'])
        for name, meta in item['Properties'].items():
            if 'Validation' in meta:
                dict = meta['Validation']
                if dict['Type'] == "range":
                    validators[name] = (dict['Type'], dict['Validator'], dict['Unit'])
                else:
                    validators[name] = (dict['Type'], dict['Validator'])
%>
% for index, intf in enumerate(interfaces):
using Iface${index} = ${get_setting_sdbusplus_type(intf)};
<% aliases.append("Iface" + str(index)) %>\
% endfor
<%
    parent = "sdbusplus::server::object_t" + "<" + ", ".join(aliases) + ">"
%>\
using Parent = ${parent};

class Impl : public Parent
{
    public:
        Impl(sdbusplus::bus_t& bus, const char* path):
            Parent(bus, path, Parent::action::defer_emit),
            path(path)
        {
        }
        virtual ~Impl() = default;

        void setInitialVersion(std::uint32_t v)
        {
            initialVersion = v;
        }

        std::uint32_t getInitialVersion() const
        {
            return initialVersion;
        }

        bool deserialize()
        {
            auto p = getFilePath(path);
            if (fs::exists(p))
            {
                std::ifstream is(p.c_str(), std::ios::in);
                cereal::JSONInputArchive iarchive(is);
                iarchive(*this);
                return true;
            }
            return false;
        }

        void serialize()
        {
            auto p = getFilePath(path);
            if (!fs::exists(p.parent_path()))
            {
                fs::create_directories(p.parent_path());
            }
            std::ofstream os(p.c_str(), std::ios::binary);
            cereal::JSONOutputArchive oarchive(os);
            oarchive(*this);
        }

        void removeFile() const
        {
            std::error_code ec;
            fs::remove(getFilePath(path), ec);
        }

% for index, item in enumerate(settingsDict[object]):
    % for propName, metaDict in item['Properties'].items():
<% t = NamedElement(name=propName).camelCase %>\
<% fname = "validate" + propName %>\
        decltype(std::declval<Iface${index}>().${t}()) ${t}(decltype(std::declval<Iface${index}>().${t}()) value) override
        {
            auto result = Iface${index}::${t}();
            if (value != result)
            {
            % if propName in validators:
                if (!${fname}(value))
                {
                    namespace error =
                        sdbusplus::xyz::openbmc_project::Common::Error;
                    namespace metadata =
                        phosphor::logging::xyz::openbmc_project::Common;
                    phosphor::logging::report<error::InvalidArgument>(
                        metadata::InvalidArgument::ARGUMENT_NAME("${t}"),
                    % if validators[propName][0] != "regex":
                        metadata::InvalidArgument::ARGUMENT_VALUE(std::to_string(value).c_str()));
                    % else:
                        metadata::InvalidArgument::ARGUMENT_VALUE(value.c_str()));
                    % endif
                    return result;
                }
             % endif
                result = Iface${index}::${t}(value);
                serialize();
            }
            return result;
        }
        using Iface${index}::${t};

    % endfor
% endfor
    private:
        fs::path path;
        std::uint32_t initialVersion = 0;
% for index, item in enumerate(settingsDict[object]):
  % for propName, metaDict in item['Properties'].items():
<% t = NamedElement(name=propName).camelCase %>\
<% fname = "validate" + propName %>\
    % if propName in validators:

        bool ${fname}(decltype(std::declval<Iface${index}>().${t}()) value)
        {
            bool matched = false;
        % if (validators[propName][0] == 'regex'):
            std::regex regexToCheck("${validators[propName][1]}");
            matched = std::regex_search(value, regexToCheck);
            if (!matched)
            {
                std::string err = "Input parameter for ${propName} is invalid "
                    "Input: " + value + " not in the format of this regex: "
                    "${validators[propName][1]}";
                using namespace phosphor::logging;
                log<level::ERR>(err.c_str());
            }
        % elif (validators[propName][0] == 'range'):
<% lowhigh = re.split('\.\.', validators[propName][1]) %>\
        % if lowhigh[0] == '0':
            if (value <= ${lowhigh[1]})
        % else:
            if ((value <= ${lowhigh[1]}) && (value >= ${lowhigh[0]}))
        % endif
            {
                matched = true;
            }
            else
            {
                std::string err = "Input parameter for ${propName} is invalid "
                    "Input: " + std::to_string(value) + "in uint: "
                    "${validators[propName][2]} is not in range:${validators[propName][1]}";
                using namespace phosphor::logging;
                log<level::ERR>(err.c_str());
            }
        % else:
            <% assert("Unknown validation type: propName") %>\
        % endif
            return matched;
        }
    % endif
  % endfor
% endfor
};

template<class Archive>
void save(Archive& a,
          const Impl& setting,
          [[maybe_unused]] const std::uint32_t version)
{
<%
props = []
for index, item in enumerate(settingsDict[object]):
    props.extend(item['Properties'].keys())
%>\
## Since the iface isn't saved, property names need to be unique on
## the object path.  This could be supported by providing unique
## field names to make_nvp() if ever necessary.
% if len(set(props)) != len(props):
#error Duplicate property names on object path ${object}
%endif
<%
args = []
for prop in props:
    t = "setting." + NamedElement(name=prop).camelCase + "()"
    args.append(f"cereal::make_nvp(\"{prop}\", {t})")
args = ", ".join(args)
%>\
    a(${args});
}

template<class Archive>
void load(Archive& a,
          Impl& setting,
          const std::uint32_t version)
{
    setting.setInitialVersion(version);
<%
props = []
for index, item in enumerate(settingsDict[object]):
    for prop in item['Properties'].keys():
        t = "setting." + NamedElement(name=prop).camelCase + "()"
        props.append({'prop' : prop, 'iface': item['Interface'], 'func': t})
%>\
% for p in props:
    decltype(${p['func']}) ${p['prop']}{};
% endfor
<% propList = ', '.join([p['prop'] for p in props]) %>
% if propList:
    if (version < CLASS_VERSION_WITH_NVP)
    {
        a(${propList});
    }
    else
    {
    % for p in props:
        try
        {
            a(CEREAL_NVP(${p['prop']}));
        }
        catch (const cereal::Exception& e)
        {
            lg2::info("Could not restore property ${p['prop']} on ${object}, setting to default value");
            ${p['prop']} = ${get_default_value(object, p['iface'], p['prop'])};
        }
    % endfor
    }
% endif
<% props = [] %>
% for index, item in enumerate(settingsDict[object]):
  % for  prop, metaDict in item['Properties'].items():
<%
    t = "setting." + NamedElement(name=prop).camelCase + "(" + prop + ")"
%>\
    ${t};
  % endfor
% endfor
}

% for n in reversed(ns):
} // namespace ${n}
% endfor

% endfor

/** @class Manager
 *
 *  @brief Compose settings objects and put them on the bus.
 */
class Manager
{
    public:
        Manager() = delete;
        Manager(const Manager&) = delete;
        Manager& operator=(const Manager&) = delete;
        Manager(Manager&&) = delete;
        Manager& operator=(Manager&&) = delete;
        virtual ~Manager() = default;

        /** @brief Constructor to put settings objects on to the bus.
         *  @param[in] bus - Bus to attach to.
         */
        explicit Manager(sdbusplus::bus_t& bus) :
            settings(
                std::make_tuple(
% for index, path in enumerate(objects):
<% type = get_setting_type(path) + "::Impl" %>\
                    std::make_unique<${type}>(
                        bus,
  % if index < len(settingsDict) - 1:
                        "${path}"),
  % else:
                        "${path}")
  % endif
% endfor
                )
            )
        {
% for index, path in enumerate(objects):
            auto initSetting${index} = [&]()
            {
  % for item in settingsDict[path]:
    % for propName, metaDict in item['Properties'].items():
<% p = NamedElement(name=propName).camelCase %>\
<% defaultValue = get_default_value(path, item['Interface'], propName) %>\
                std::get<${index}>(settings)->
                  ${get_setting_sdbusplus_type(item['Interface'])}::${p}(${defaultValue});
  % endfor
% endfor
            };

            try
            {
                if (std::get<${index}>(settings)->deserialize())
                {
                    /* Update the archive to use name/value pairs if it isn't. */
                    if (std::get<${index}>(settings)->getInitialVersion() < CLASS_VERSION_WITH_NVP)
                    {
                        std::get<${index}>(settings)->serialize();
                    }
                }
                else
                {
                    initSetting${index}();
                }
            }
            catch (const cereal::Exception& e)
            {
                log<level::ERR>(e.what());
                std::get<${index}>(settings)->removeFile();
                initSetting${index}();
            }
            std::get<${index}>(settings)->emit_object_added();

% endfor
        }

    private:
        /* @brief Composition of settings objects. */
        std::tuple<
% for index, path in enumerate(objects):
<% type = get_setting_type(path) + "::Impl" %>\
  % if index < len(settingsDict) - 1:
            std::unique_ptr<${type}>,
  % else:
            std::unique_ptr<${type}>> settings;
  % endif
% endfor
};

} // namespace settings
} // namespace phosphor

// Now register the class version with Cereal
% for object in objects:
<%
   classname = "phosphor::settings"
   ns = object.split('/')
   ns.pop(0)
%>\
% for n in ns:
<%
    classname += "::" + n
%>\
% endfor
CEREAL_CLASS_VERSION(${classname + "::Impl"}, CLASS_VERSION);
% endfor
