/*
// Copyright (c) 2018 Intel 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 "dbus/dbuswrite.hpp"

#include <iostream>
#include <memory>
#include <phosphor-logging/log.hpp>
#include <sdbusplus/bus.hpp>
#include <string>

constexpr const char* pwmInterface = "xyz.openbmc_project.Control.FanPwm";

using namespace phosphor::logging;

// this bus object is treated as a singleton because the class is constructed in
// a different thread than it is used, and as bus objects are relatively
// expensive we'd prefer to only have one
std::unique_ptr<sdbusplus::bus::bus> writeBus = nullptr;

std::unique_ptr<WriteInterface>
    DbusWritePercent::createDbusWrite(const std::string& path, int64_t min,
                                      int64_t max, DbusHelperInterface& helper)
{
    auto tempBus = sdbusplus::bus::new_default();
    std::string connectionName;

    try
    {
        connectionName = helper.getService(tempBus, pwmInterface, path);
    }
    catch (const std::exception& e)
    {
        return nullptr;
    }

    return std::make_unique<DbusWritePercent>(path, min, max, connectionName);
}

void initBus()
{
    if (writeBus == nullptr)
    {
        writeBus = std::make_unique<sdbusplus::bus::bus>(
            sdbusplus::bus::new_default());
    }
}

void DbusWritePercent::write(double value)
{
    double minimum = getMin();
    double maximum = getMax();

    double range = maximum - minimum;
    double offset = range * value;
    double ovalue = offset + minimum;

    if (oldValue == static_cast<int64_t>(ovalue))
    {
        return;
    }
    initBus();
    auto mesg =
        writeBus->new_method_call(connectionName.c_str(), path.c_str(),
                                  "org.freedesktop.DBus.Properties", "Set");
    mesg.append(pwmInterface, "Target",
                sdbusplus::message::variant<uint64_t>(ovalue));

    try
    {
        // TODO: if we don't use the reply, call_noreply()
        auto resp = writeBus->call(mesg);
    }
    catch (const sdbusplus::exception::SdBusError& ex)
    {
        log<level::ERR>("Dbus Call Failure", entry("PATH=%s", path.c_str()),
                        entry("WHAT=%s", ex.what()));
    }

    oldValue = static_cast<int64_t>(ovalue);
    return;
}

std::unique_ptr<WriteInterface>
    DbusWrite::createDbusWrite(const std::string& path, int64_t min,
                               int64_t max, DbusHelperInterface& helper)
{
    auto tempBus = sdbusplus::bus::new_default();
    std::string connectionName;

    try
    {
        connectionName = helper.getService(tempBus, pwmInterface, path);
    }
    catch (const std::exception& e)
    {
        return nullptr;
    }

    return std::make_unique<DbusWrite>(path, min, max, connectionName);
}

void DbusWrite::write(double value)
{
    if (oldValue == static_cast<int64_t>(value))
    {
        return;
    }
    initBus();
    auto mesg =
        writeBus->new_method_call(connectionName.c_str(), path.c_str(),
                                  "org.freedesktop.DBus.Properties", "Set");
    mesg.append(pwmInterface, "Target",
                sdbusplus::message::variant<uint64_t>(value));

    try
    {
        // TODO: consider call_noreplly
        auto resp = writeBus->call(mesg);
    }
    catch (const sdbusplus::exception::SdBusError& ex)
    {
        log<level::ERR>("Dbus Call Failure", entry("PATH=%s", path.c_str()),
                        entry("WHAT=%s", ex.what()));
    }

    oldValue = static_cast<int64_t>(value);
    return;
}
