#include <myapp/modbus/device.h>

namespace myapp::modbus {

device::device(std::string name, int slave_id, std::shared_ptr<connection> conn, std::shared_ptr<logging::logger> logger)
  : name_(std::move(name))
  , slave_id_(slave_id)
  , data_access_(conn->get_data_access())
  , executor_(conn->get_poller()->executor())
  , logger_(std::move(logger))
{
    logger_->info("MODBUS DEVICE", "Modbus device '" + name_ + "' created with slave id '" + std::to_string(slave_id_) + "'");
}

std::string const& device::get_name() const noexcept
{
    return name_;
}

std::string device::handle_command(std::string cmd) noexcept
{
    try
    {
        return handle_command_impl(cmd);
    }
    catch (std::exception& e)
    {
        using namespace std::string_literals;
        logger_->warning("MODBUS DEVICE", "Device '" + name_ + "' throws an exception on command '" + cmd + "': " + e.what());
        return "Exception has been thrown: "s + e.what() + "."s;
    }
}

void device::status_update_callback(std::function<void(std::string, std::string)> value) noexcept
{
    status_update_callback_ = std::move(value);
}

void device::raise_status_update(std::string key, std::string value)
{
    using namespace std::string_literals;
    auto full_key = get_name() + ":"s + std::move(key);
    logger_->debug("MODBUS DEVICE", "Publishing state change '" + full_key + "' with value '" + value + "'");

    if (status_update_callback_)
        status_update_callback_(std::move(full_key), std::move(value));
}

} /* namespace myapp::modbus */
