/*
 * Copyright (C) 2020 CESNET, https://photonics.cesnet.cz/
 *
 * Written by Václav Kubernát <kubernat@cesnet.cz>
 *
*/
#include <boost/algorithm/string/predicate.hpp>
#include "proxy_datastore.hpp"
#include "yang_schema.hpp"

ProxyDatastore::ProxyDatastore(const std::shared_ptr<DatastoreAccess>& datastore, std::function<std::shared_ptr<DatastoreAccess>(const std::shared_ptr<DatastoreAccess>&)> createTemporaryDatastore)
    : m_datastore(datastore)
    , m_createTemporaryDatastore(createTemporaryDatastore)
{
}

DatastoreAccess::Tree ProxyDatastore::getItems(const std::string& path) const
{
    return pickDatastore(path)->getItems(path);
}

void ProxyDatastore::setLeaf(const std::string& path, leaf_data_ value)
{
    pickDatastore(path)->setLeaf(path, value);
}

void ProxyDatastore::createItem(const std::string& path)
{
    pickDatastore(path)->createItem(path);
}

void ProxyDatastore::deleteItem(const std::string& path)
{
    pickDatastore(path)->deleteItem(path);
}

void ProxyDatastore::moveItem(const std::string& source, std::variant<yang::move::Absolute, yang::move::Relative> move)
{
    pickDatastore(source)->moveItem(source, move);
}

void ProxyDatastore::commitChanges()
{
    m_datastore->commitChanges();
}

void ProxyDatastore::discardChanges()
{
    m_datastore->discardChanges();
}

void ProxyDatastore::copyConfig(const Datastore source, const Datastore destination)
{
    m_datastore->copyConfig(source, destination);
}

std::string ProxyDatastore::dump(const DataFormat format) const
{
    return m_datastore->dump(format);
}

namespace {
struct getInputPath {
    template <typename InputType>
    auto operator()(const InputType& input)
    {
        return input.m_path;
    }
};
}

void ProxyDatastore::initiateRpc(const std::string& rpcPath)
{
    if (m_inputDatastore) {
        throw std::runtime_error("RPC/action input already in progress (" + std::visit(getInputPath{}, m_inputPath) + ")");
    }
    m_inputDatastore = m_createTemporaryDatastore(m_datastore);
    m_inputPath = RpcInput{rpcPath};
    m_inputDatastore->createItem(rpcPath);
}

void ProxyDatastore::initiateAction(const std::string& actionPath)
{
    if (m_inputDatastore) {
        throw std::runtime_error("RPC/action input already in progress (" + std::visit(getInputPath{}, m_inputPath) + ")");
    }
    m_inputDatastore = m_createTemporaryDatastore(m_datastore);
    m_inputPath = ActionInput{actionPath};
    m_inputDatastore->createItem(actionPath);
}

DatastoreAccess::Tree ProxyDatastore::execute()
{
    if (!m_inputDatastore) {
        throw std::runtime_error("No RPC/action input in progress");
    }
    auto inputData = m_inputDatastore->getItems("/");
    m_inputDatastore = nullptr;
    if (std::holds_alternative<RpcInput>(m_inputPath)) {
        return m_datastore->executeRpc(std::visit(getInputPath{}, m_inputPath), inputData);
    } else {
        return m_datastore->executeAction(std::visit(getInputPath{}, m_inputPath), inputData);
    }
}

void ProxyDatastore::cancel()
{
    m_inputDatastore = nullptr;
}

std::shared_ptr<Schema> ProxyDatastore::schema() const
{
    return m_datastore->schema();
}

std::shared_ptr<DatastoreAccess> ProxyDatastore::pickDatastore(const std::string& path) const
{
    if (!m_inputDatastore || !boost::starts_with(path, std::visit(getInputPath{}, m_inputPath))) {
        return m_datastore;
    } else {
        return m_inputDatastore;
    }
}
