#pragma once

#include "xyz/openbmc_project/Common/FilePath/server.hpp"
#include "xyz/openbmc_project/Inventory/Decorator/Compatible/server.hpp"
#include "xyz/openbmc_project/Object/Delete/server.hpp"
#include "xyz/openbmc_project/Software/ExtendedVersion/server.hpp"
#include "xyz/openbmc_project/Software/Version/server.hpp"

#include <sdbusplus/bus.hpp>

#include <functional>
#include <string>
#include <vector>

namespace phosphor
{
namespace software
{
namespace manager
{

typedef std::function<void(std::string)> eraseFunc;

using VersionInherit = sdbusplus::server::object_t<
    sdbusplus::server::xyz::openbmc_project::software::ExtendedVersion,
    sdbusplus::server::xyz::openbmc_project::software::Version,
    sdbusplus::server::xyz::openbmc_project::common::FilePath,
    sdbusplus::server::xyz::openbmc_project::inventory::decorator::Compatible>;
using DeleteInherit = sdbusplus::server::object_t<
    sdbusplus::server::xyz::openbmc_project::object::Delete>;

class Version;
class Delete;

/** @class Delete
 *  @brief OpenBMC Delete implementation.
 *  @details A concrete implementation for xyz.openbmc_project.Object.Delete
 *  D-Bus API.
 */
class Delete : public DeleteInherit
{
  public:
    /** @brief Constructs Delete.
     *
     *  @param[in] bus    - The D-Bus bus object
     *  @param[in] path   - The D-Bus object path
     *  @param[in] parent - Parent object.
     */
    Delete(sdbusplus::bus_t& bus, const std::string& path, Version& parent) :
        DeleteInherit(bus, path.c_str(), action::emit_interface_added),
        parent(parent)
    {
        // Empty
    }

    /** @brief delete the D-Bus object. */
    void delete_() override;

  private:
    /** @brief Parent Object. */
    Version& parent;
};

/** @class Version
 *  @brief OpenBMC version software management implementation.
 *  @details A concrete implementation for xyz.openbmc_project.Software.Version
 *  D-Bus API.
 */
class Version : public VersionInherit
{
  public:
    /** @brief Constructs Version Software Manager
     *
     * @param[in] bus             - The D-Bus bus object
     * @param[in] objPath         - The D-Bus object path
     * @param[in] versionString   - The version string
     * @param[in] versionPurpose  - The version purpose
     * @param[in] extVersion      - The extended version
     * @param[in] filePath        - The image filesystem path
     * @param[in] compatibleNames - The device compatibility names
     * @param[in] callback        - The eraseFunc callback
     */
    Version(sdbusplus::bus_t& bus, const std::string& objPath,
            const std::string& versionString, VersionPurpose versionPurpose,
            const std::string& extVersion, const std::string& filePath,
            const std::vector<std::string>& compatibleNames, eraseFunc callback,
            const std::string& id) :
        VersionInherit(bus, (objPath).c_str(),
                       VersionInherit::action::defer_emit),
        eraseCallback(std::move(callback)), id(id), versionStr(versionString)
    {
        // Set properties.
        extendedVersion(extVersion);
        purpose(versionPurpose);
        version(versionString);
        path(filePath);
        names(compatibleNames);
        // Emit deferred signal.
        emit_object_added();
    }

    /**
     * @brief Read the manifest file to get the value of the key.
     *
     * @return The value of the key.
     **/
    static std::string getValue(const std::string& manifestFilePath,
                                std::string key);

    /**
     * @brief Read the manifest file to get the values of the repeated key.
     *
     * @return The values of the repeated key.
     **/
    static std::vector<std::string>
        getRepeatedValues(const std::string& manifestFilePath, std::string key);

    /**
     * @brief Calculate the version id from the version string.
     *
     * @details The version id is a unique 8 hexadecimal digit id
     *          calculated from the version string.
     *
     * @param[in] versionWithSalt - The image's version string
     *                              (e.g. v1.99.10-19) plus an optional salt
     *                              string.
     *
     * @return The id.
     */
    static std::string getId(const std::string& versionWithSalt);

    /**
     * @brief Get the active BMC machine name string.
     *
     * @param[in] releaseFilePath - The path to the file which contains
     *                              the release machine string.
     *
     * @return The machine name string (e.g. romulus, tiogapass).
     */
    static std::string getBMCMachine(const std::string& releaseFilePath);

    /**
     * @brief Get the BMC Extended Version string.
     *
     * @param[in] releaseFilePath - The path to the file which contains
     *                              the release machine string.
     *
     * @return The extended version string.
     */
    static std::string
        getBMCExtendedVersion(const std::string& releaseFilePath);

    /**
     * @brief Get the active BMC version string.
     *
     * @param[in] releaseFilePath - The path to the file which contains
     *                              the release version string.
     *
     * @return The version string (e.g. v1.99.10-19).
     */
    static std::string getBMCVersion(const std::string& releaseFilePath);

    /* @brief Check if this version is functional.
     *
     * @return - Returns the functional value.
     */
    bool isFunctional() const
    {
        return functional;
    }

    /** @brief Set the functional value.
     * @param[in] value - True or False
     */
    void setFunctional(bool value)
    {
        functional = value;
    }

    /** @brief Persistent Delete D-Bus object */
    std::unique_ptr<Delete> deleteObject;

    /** @brief The parent's erase callback. */
    eraseFunc eraseCallback;

    /** @brief The version ID of the object */
    const std::string id;

  private:
    /** @brief This Version's version string */
    const std::string versionStr;

    /** @brief If this version is the functional one */
    bool functional = false;
};

} // namespace manager
} // namespace software
} // namespace phosphor
