//
//  SwitchboardObject.hpp
//  SwitchboardSDK
//
//  Created by Balazs Kiss on 2025. 01. 22..
//

#pragma once

#include <switchboard/export.h>
#include <switchboard_core/EventEmitter.hpp>
#include <switchboard/SBAny.hpp>
#include <switchboard_core/SwitchboardCore.hpp>
#include <switchboard_core/Configuration.hpp>
#include <switchboard_core/Property.hpp>
#include <switchboard_core/Action.hpp>
#include <switchboard_core/Event.hpp>

#include <any>
#include <map>
#include <memory>
#include <string>
#include <switchboard/Result.hpp>

namespace switchboard {

namespace SwitchboardObjectType {
    inline constexpr const char* SWITCHBOARD = "switchboard";
    inline constexpr const char* ENGINE = "engine";
    inline constexpr const char* GRAPH = "graph";
    inline constexpr const char* NODE = "node";
    inline constexpr const char* EXTENSION = "extension";
}

/**
 * @brief SwitchboardObject interface.
 */
class SWITCHBOARDSDK_EXPORT SwitchboardObject : public EventEmitter {
public:

    /**
     * @brief SwitchboardObject constructor.
     *
     * @param objectType The type of the object.
     */
    explicit SwitchboardObject(const std::string& objectType);

    /**
     * @brief SwitchboardObject destructor.
     */
    ~SwitchboardObject() override;

    /**
     * @brief Gets the ID of the object.
     *
     * @return The ID of the object.
     */
    std::string getObjectID() const;

    /**
     * @brief Sets the ID of the object.
     *
     * @param objectID The ID to set.
     */
    void setObjectID(const std::string& objectID);

    /**
     * @brief Gets the URI of the object.
     *
     * @return The URI of the object.
     */
    std::string getURI();

    /**
     * @brief Gets the type of the object.
     *
     * @return The type of the object.
     */
    std::string getObjectType() const;

    /**
     * @brief Gets the subtype of the object.
     *
     * @return The subtype of the object, or nullopt if not set.
     */
    std::optional<std::string> getObjectSubtype() const;

    /**
     * @brief Sets the subtype of the object.
     *
     * @param subtype The subtype to set.
     */
    void setObjectSubtype(std::optional<std::string> subtype);

    /**
     * @brief Gets the parent object of the object.
     *
     * @return The parent object of the object.
     */
    SwitchboardObject* getParentObject() const;

    /**
     * @brief Sets the parent object of the object.
     *
     * @param parentObject The parent object to set.
     */
    void setParentObject(SwitchboardObject* parentObject);

    /**
     * @brief Sets a value on the object.
     *
     * @param key The key of the value.
     * @param value The value to set.
     *
     * @return A successful result if the value was set successfully, an error result otherwise.
     */
    virtual Result<void> setValue(const std::string& key, const SBAny& value);

    /**
     * @brief Gets a value from the object.
     *
     * @param key The key of the value.
     *
     * @return The value.
     */
    virtual Result<SBAny> getValue(const std::string& key);

    /**
     * @brief Calls an action on the object.
     *
     * @param actionName The name of the action.
     * @param params The parameters of the action.
     *
     * @return The result of the action.
     */
    virtual Result<SBAny> callAction(const std::string& actionName, const SBAnyMap& params);

    /**
     * @brief Registers a configuration for the object.
     *
     * @param key The key of the configuration.
     * @param configuration The configuration to register.
     */
    void registerConfiguration(const std::string& key, const SBAnyMap& configuration);

    /**
     * @brief Sets a configuration value for the object.
     *
     * @param key The key of the configuration.
     * @param value The value to set.
     */
    void setConfigurationValue(const std::string& key, const SBAny& value);

    /**
     * @brief Registers a property for the object.
     *
     * @param key The key of the property.
     * @param propertyInfo The information about the property.
     */
    void registerProperty(const std::string& key, const SBAnyMap& propertyInfo);

    /**
     * @brief Registers an action for the object.
     *
     * @param key The key of the action.
     * @param actionInfo The information about the action.
     */
    void registerAction(const std::string& key, const SBAnyMap& actionInfo);

    /**
     * @brief Registers an event for the object.
     *
     * @param eventName The name of the event.
     * @param eventInfo The information about the event.
     */
    void registerEvent(const std::string& eventName, const SBAnyMap& eventInfo);

private:
    class Impl;
    std::unique_ptr<Impl> impl;
};

}
