#pragma once

#include <softbus_core/models/ObjectModel.h>
#include <softbus_registry/PointTableEntry.h>

#include <optional>
#include <string>
#include <unordered_map>
#include <vector>

namespace softbus::registry {

class PointRegistry {
public:
    bool loadPointTable(const std::string& path);
    bool loadTopicRules(const std::string& path);

    const softbus::core::ObjectModelTree& tree() const { return tree_; }
    const TopicRules& topicRules() const { return topicRules_; }
    const std::vector<PointTableEntry>& entries() const { return entries_; }

    std::optional<PointTableEntry> findByObjectRef(const std::string& objectRef) const;
    std::optional<PointTableEntry> findByTopic(const std::string& topic) const;
    std::optional<PointTableEntry> findByOpcuaNodeId(const std::string& nodeId) const;
    std::optional<PointTableEntry> findByDevicePoint(const std::string& deviceId,
                                                   const std::string& pointId) const;
    std::optional<softbus::core::ObjectRef> findPointByRegister(int registerAddress) const;
    bool validateWriteValue(const PointTableEntry& entry, double value, std::string* error) const;

private:
    void indexEntry(const PointTableEntry& entry);

    softbus::core::ObjectModelTree tree_;
    TopicRules topicRules_;
    std::vector<PointTableEntry> entries_;
    std::unordered_map<std::string, std::size_t> byObjectRef_;
    std::unordered_map<std::string, std::size_t> byTopic_;
    std::unordered_map<std::string, std::size_t> byOpcuaNodeId_;
    std::unordered_map<std::string, std::size_t> byDevicePoint_;
};

} // namespace softbus::registry
