#include "config.h"

#include "serialize.hpp"

#include <cereal/archives/json.hpp>
#include <experimental/filesystem>
#include <fstream>
#include <phosphor-logging/log.hpp>
#include <sdbusplus/server.hpp>

namespace phosphor
{
namespace software
{
namespace updater
{

using namespace phosphor::logging;
namespace fs = std::experimental::filesystem;

const std::string priorityName = "priority";
const std::string purposeName = "purpose";

void storePriority(const std::string& versionId, uint8_t priority)
{
    auto path = fs::path(PERSIST_DIR) / versionId;
    if (!fs::is_directory(path))
    {
        if (fs::exists(path))
        {
            // Delete if it's a non-directory file
            log<level::WARNING>("Removing non-directory file",
                                entry("PATH=%s", path.c_str()));
            fs::remove_all(path);
        }
        fs::create_directories(path);
    }
    path = path / priorityName;

    std::ofstream os(path.c_str());
    cereal::JSONOutputArchive oarchive(os);
    oarchive(cereal::make_nvp(priorityName, priority));
}

void storePurpose(const std::string& versionId, VersionPurpose purpose)
{
    auto path = fs::path(PERSIST_DIR) / versionId;
    if (!fs::is_directory(path))
    {
        if (fs::exists(path))
        {
            // Delete if it's a non-directory file
            log<level::WARNING>("Removing non-directory file",
                                entry("PATH=%s", path.c_str()));
            fs::remove_all(path);
        }
        fs::create_directories(path);
    }
    path = path / purposeName;

    std::ofstream os(path.c_str());
    cereal::JSONOutputArchive oarchive(os);
    oarchive(cereal::make_nvp(purposeName, purpose));
}

bool restorePriority(const std::string& versionId, uint8_t& priority)
{
    auto path = fs::path(PERSIST_DIR) / versionId / priorityName;
    if (fs::exists(path))
    {
        std::ifstream is(path.c_str(), std::ios::in);
        try
        {
            cereal::JSONInputArchive iarchive(is);
            iarchive(cereal::make_nvp(priorityName, priority));
            return true;
        }
        catch (cereal::Exception& e)
        {
            fs::remove_all(path);
        }
    }

    // Find the mtd device "u-boot-env" to retrieve the environment variables
    std::ifstream mtdDevices("/proc/mtd");
    std::string device, devicePath;

    try
    {
        while (std::getline(mtdDevices, device))
        {
            if (device.find("u-boot-env") != std::string::npos)
            {
                devicePath = "/dev/" + device.substr(0, device.find(':'));
                break;
            }
        }

        if (!devicePath.empty())
        {
            std::ifstream input(devicePath.c_str());
            std::string envVars;
            std::getline(input, envVars);

            std::string versionVar = versionId + "=";
            auto varPosition = envVars.find(versionVar);

            if (varPosition != std::string::npos)
            {
                // Grab the environment variable for this versionId. These
                // variables follow the format "versionId=priority\0"
                auto var = envVars.substr(varPosition);
                priority = std::stoi(var.substr(versionVar.length()));
                return true;
            }
        }
    }
    catch (const std::exception& e)
    {
    }

    return false;
}

bool restorePurpose(const std::string& versionId, VersionPurpose& purpose)
{
    auto path = fs::path(PERSIST_DIR) / versionId / purposeName;
    if (fs::exists(path))
    {
        std::ifstream is(path.c_str(), std::ios::in);
        try
        {
            cereal::JSONInputArchive iarchive(is);
            iarchive(cereal::make_nvp(purposeName, purpose));
            return true;
        }
        catch (cereal::Exception& e)
        {
            fs::remove_all(path);
        }
    }

    return false;
}

void removePersistDataDirectory(const std::string& versionId)
{
    auto path = fs::path(PERSIST_DIR) / versionId;
    if (fs::exists(path))
    {
        fs::remove_all(path);
    }
}

} // namespace updater
} // namespace software
} // namespace phosphor
