/*
 * Copyright (C) 2020 CESNET, https://photonics.cesnet.cz/
 *
 * Written by Václav Kubernát <kubernat@cesnet.cz>
 *
*/

#pragma once

#include "datastore_access.hpp"

/*! \class YangAccess
 *     \brief Implementation of DatastoreAccess with a local libyang data node instance
 */

class YangSchema;

struct ly_ctx;
struct lyd_node;

class YangAccess : public DatastoreAccess {
public:
    YangAccess();
    ~YangAccess() override;
    [[nodiscard]] Tree getItems(const std::string& path) const override;
    void setLeaf(const std::string& path, leaf_data_ value) override;
    void createItem(const std::string& path) override;
    void deleteItem(const std::string& path) override;
    void moveItem(const std::string& source, std::variant<yang::move::Absolute, yang::move::Relative> move) override;
    void commitChanges() override;
    void discardChanges() override;
    Tree executeRpc(const std::string& path, const Tree& input) override;
    void copyConfig(const Datastore source, const Datastore destination) override;

    std::shared_ptr<Schema> schema() override;

    void enableFeature(const std::string& module, const std::string& feature);
    [[nodiscard]] std::string dump(const DataFormat format) const override;

    void loadModule(const std::string& name);
    void addSchemaFile(const std::string& path);
    void addSchemaDir(const std::string& path);
    void addDataFile(const std::string& path);

private:
    std::vector<ListInstance> listInstances(const std::string& path) override;

    [[noreturn]] void getErrorsAndThrow() const;
    void impl_newPath(const std::string& path, const std::optional<std::string>& value = std::nullopt);
    void impl_removeNode(const std::string& path);
    void validate();

    std::unique_ptr<ly_ctx, void(*)(ly_ctx*)> m_ctx;
    std::unique_ptr<lyd_node, void(*)(lyd_node*)> m_datastore;
    std::shared_ptr<YangSchema> m_schema;
};
