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

#include "client/UaSubscription.h"
#include "client/UaClient.h"

UaSubscription::UaSubscription(UaClient& client) : _opcUaClient(client) {}

UaSubscription::~UaSubscription() {
    // Delete all monitored items
    DeleteSubscription();
}

bool UaSubscription::CreateSubscription(const double publishInterval, const int priority) {
    _request = UA_CreateSubscriptionRequest_default();
    _request.requestedPublishingInterval = publishInterval;
    _request.priority = priority;

    // TODO put connection somewhere else or hold connection state inside UaSubscription
    _response = UA_Client_Subscriptions_create(_opcUaClient.GetClient(), _request, this, StatusChangeNotificationCallback, DeleteSubscriptionCallback);
    _isCreated = _response.responseHeader.serviceResult == UA_STATUSCODE_GOOD;
    return _isCreated;
}

void UaSubscription::ModifySubscription() {
    UA_ModifySubscriptionRequest request;
    UA_ModifySubscriptionRequest_init(&request);

    UA_ModifySubscriptionResponse response = UA_Client_Subscriptions_modify(_opcUaClient.GetClient(), request);
    UA_StatusCode status = response.responseHeader.serviceResult;
}

void UaSubscription::DeleteSubscription() {
    UA_StatusCode status = UA_Client_Subscriptions_deleteSingle(_opcUaClient.GetClient(), _response.subscriptionId);
    //_monitoredItems.clear();

    if(status == UA_STATUSCODE_GOOD)
        _isCreated = false;
}

void UaSubscription::SetPublishingMode(bool enable) {
    UA_SetPublishingModeRequest request;
    UA_SetPublishingModeRequest_init(&request);
    request.publishingEnabled = enable;

    UA_SetPublishingModeResponse response = UA_Client_Subscriptions_setPublishingMode(_opcUaClient.GetClient(), request);
    UA_StatusCode status = response.results[0];
}

unsigned UaSubscription::AddMonitoredItem(UaNodeId node, MonitorItemFunc func) {
    auto monItem = new MonitoredItemDataChange(*this, func);
    if(monItem->AddDataChange(node)) {
        MonitoredItemRef item(monItem);
        _monitoredItems[item->GetId()] = item;
        return item->GetId();
    }
    delete monItem;
    return 0;
}

void UaSubscription::AddMonitoredItems(std::vector<UaNodeId> nodeIds) {
    //UA_CreateMonitoredItemsRequest request;
    //UA_Client_MonitoredItems_createDataChanges(
}