//
// Created by magino on 21.7.2019.
//

#ifndef UASUBSCRIPTION_H
#define UASUBSCRIPTION_H

#include <iostream>
#include <vector>
#include <memory>
#include <map>

class UaClient;

#include "UaMonitoredItem.h"

typedef std::shared_ptr<UaMonitoredItem> MonitoredItemRef;
typedef std::map<unsigned, MonitoredItemRef> MonitoredItemMap;

/*
 * Subscription Service Set
 * ^^^^^^^^^^^^^^^^^^^^^^^^ */
class UaSubscription {
private:
    UaClient& _opcUaClient;
    UA_CreateSubscriptionRequest _request;
    UA_CreateSubscriptionResponse _response;
    MonitoredItemMap _monitoredItems;
    bool _isCreated;

protected:
    // TODO how to use this callbacks
    static void DeleteSubscriptionCallback(UA_Client *, UA_UInt32, void* subContext) {
        //UaSubscription* sub = (UaSubscription*)(subContext);
        //if (sub) sub->DeleteSubscription();
    }

    static void StatusChangeNotificationCallback(UA_Client* /*client*/, UA_UInt32 /*subId*/, void* subContext,
                                                 UA_StatusChangeNotification* notification) {
        //UaSubscription *sub = (ClientSubscription *)(subContext);
        //if (sub) sub->StatusChangeNotification(notification);
    }

public:
    UaSubscription(UaClient& client);
    virtual ~UaSubscription();

    bool CreateSubscription(const double publishInterval = 500.0, const int priority = 0);

    void ModifySubscription();
    // UA_Client_Subscriptions_delete
    void DeleteSubscription();
    void SetPublishingMode(bool enable);

    UaClient& GetOpcUaClient() { return _opcUaClient; }
    unsigned GetId() { return _response.subscriptionId; }

    // TODO create monitored item with custom parameters
    unsigned AddMonitoredItem(UaNodeId node, MonitorItemFunc func);
    void RemoveMonitoredItem(unsigned monitoredItemId) {
        auto item = _monitoredItems.at(monitoredItemId);
        item->Remove();
        _monitoredItems.erase(monitoredItemId);
    }

    void AddMonitoredItems(std::vector<UaNodeId> nodeIds);
    // TODO events
    // UA_Client_MonitoredItems_createEvent
    // UA_Client_MonitoredItems_createEvents

    // UA_Client_MonitoredItems_delete
    // UA_Client_MonitoredItems_deleteSingle
    // UA_Client_MonitoredItems_modify
};

#endif //UASUBSCRIPTION_H
