#include <myapp/rcon/client.h>

namespace myapp::rcon {

static std::string const g_tag = "RCON";

client::client(std::shared_ptr<logging::logger> logger, std::unique_ptr<rcon::peer_provider> peerProvider)
  : logger_(std::move(logger))
  , peerProvider_(std::move(peerProvider))
  , connection_(nullptr)
  , data_handler_([](std::string) { })
  , connected_handler_([] { })
  , closed_handler_([] { })
{
    peerProvider_->on_callback([this](std::unique_ptr<connection> conn_ptr) { on_connected(std::move(conn_ptr)); });
    peerProvider_->on_error([this](std::string err_str) { on_error(std::move(err_str)); });
}

void client::connect(std::string unix_path)
{
    logger_->notice(g_tag, "Connecting to `" + unix_path + "'");
    peerProvider_->client(std::move(unix_path));
}

void client::write(std::string msg)
{
    logger_->info(g_tag, "Command sent `" + msg + "'");
    connection_->write(std::move(msg));
}

void client::on_connected(std::unique_ptr<myapp::rcon::connection> connection)
{
    logger_->notice(g_tag, "Connected");
    connection->on_peer_closed([this] { on_closed(); });
    connection->on_data([this](std::string msg) { on_data(std::move(msg)); });
    connection_ = std::move(connection);

    connected_handler_();
}

void client::on_closed()
{
    logger_->notice(g_tag, "Connection has been closed by remote peer");
    connection_ = nullptr;

    closed_handler_();
}

void client::on_data(std::string msg)
{
    logger_->info(g_tag, "Got response `" + msg + "'");
    data_handler_(std::move(msg));
}

void client::on_error(std::string error)
{
    logger_->error(g_tag, error);

    closed_handler_();
}

void client::set_on_data(std::function<void(std::string)> handler) noexcept
{
    data_handler_ = std::move(handler);
}

void client::set_on_connected(std::function<void()> handler) noexcept
{
    connected_handler_ = std::move(handler);
}

void client::set_on_closed(std::function<void()> handler) noexcept
{
    closed_handler_ = std::move(handler);
}

} /* namespace myapp::rcon */
