/*
 * Copyright (C) 2020 CESNET, https://photonics.cesnet.cz/
 *
 * Written by Václav Kubernát <kubernat@cesnet.cz>
 *
*/
#include <boost/algorithm/string/predicate.hpp>
#include "UniqueResource.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);
}

void ProxyDatastore::initiate(const std::string& path)
{
    if (m_inputDatastore) {
        throw std::runtime_error("RPC/action input already in progress (" + *m_inputPath + ")");
    }
    m_inputDatastore = m_createTemporaryDatastore(m_datastore);
    m_inputPath = path;
    m_inputDatastore->createItem(path);
}

DatastoreAccess::Tree ProxyDatastore::execute()
{
    if (!m_inputDatastore) {
        throw std::runtime_error("No RPC/action input in progress");
    }
    auto cancelOnReturn = make_unique_resource([] {}, [this] { cancel(); });
    auto inputData = m_inputDatastore->getItems("/");

    auto out = m_datastore->execute(*m_inputPath, inputData);

    return out;
}

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

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

std::optional<std::string> ProxyDatastore::inputDatastorePath()
{
    return m_inputPath;
}

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

void ProxyDatastore::setTarget(const DatastoreTarget target)
{
    m_datastore->setTarget(target);
}
