/**
 * Copyright © 2021 IBM Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "config.h"

#include "dbus_zone.hpp"

#include "dbus_paths.hpp"
#include "sdbusplus.hpp"
#include "zone.hpp"

#include <cereal/archives/json.hpp>
#include <cereal/cereal.hpp>
#include <phosphor-logging/log.hpp>

#include <algorithm>
#include <filesystem>
#include <format>
#include <fstream>

namespace phosphor::fan::control::json
{

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

DBusZone::DBusZone(const Zone& zone) :
    ThermalModeIntf(util::SDBusPlus::getBus(),
                    (fs::path{CONTROL_OBJPATH} /= zone.getName()).c_str(),
                    ThermalModeIntf::action::defer_emit),
    _zone(zone)
{}

std::string DBusZone::current(std::string value)
{
    auto current = ThermalModeIntf::current();
    std::transform(value.begin(), value.end(), value.begin(), toupper);

    auto supported = ThermalModeIntf::supported();
    auto isSupported =
        std::any_of(supported.begin(), supported.end(), [&value](auto& s) {
            std::transform(s.begin(), s.end(), s.begin(), toupper);
            return value == s;
        });

    if (isSupported && value != current)
    {
        current = ThermalModeIntf::current(value);
        if (_zone.isPersisted(thermalModeIntf, currentProp))
        {
            saveCurrentMode();
        }
    }

    return current;
}

void DBusZone::restoreCurrentMode()
{
    auto current = ThermalModeIntf::current();
    fs::path path{CONTROL_PERSIST_ROOT_PATH};
    // Append this object's name and property description
    path /= _zone.getName();
    path /= "CurrentMode";
    fs::create_directories(path.parent_path());

    try
    {
        if (fs::exists(path))
        {
            std::ifstream ifs(path.c_str(), std::ios::in | std::ios::binary);
            cereal::JSONInputArchive iArch(ifs);
            iArch(current);
        }
    }
    catch (const std::exception& e)
    {
        // Include possible exception when removing file, otherwise ec = 0
        std::error_code ec;
        fs::remove(path, ec);
        log<level::ERR>(
            std::format("Unable to restore persisted `Current` thermal mode "
                        "property ({}, ec: {})",
                        e.what(), ec.value())
                .c_str());
        current = ThermalModeIntf::current();
    }

    this->current(current);
}

void DBusZone::saveCurrentMode()
{
    fs::path path{CONTROL_PERSIST_ROOT_PATH};
    // Append this object's name and property description
    path /= _zone.getName();
    path /= "CurrentMode";
    std::ofstream ofs(path.c_str(), std::ios::binary);
    cereal::JSONOutputArchive oArch(ofs);
    oArch(ThermalModeIntf::current());
}

} // namespace phosphor::fan::control::json
