//
// Created by magino on 3. 8. 2019.
//
#include "client/UaMonitoredItem.h"
#include "client/UaClient.h"
#include "client/UaSubscription.h"

void UaMonitoredItem::DataChangeNotificationCallback
        (UA_Client* /*client*/, UA_UInt32 /*subId*/, void* subContext,
         UA_UInt32 /*monId*/, void* monContext, UA_DataValue* value) {
    UaMonitoredItem* monItem = (UaMonitoredItem*)monContext;
    UaSubscription* sub = (UaSubscription*)subContext;
    if (monItem && sub) {
        monItem->DataChangeNotification(value);
    }
}

void UaMonitoredItem::EventNotificationCallback
        (UA_Client* /*client*/, UA_UInt32 /*subId*/, void* subContext,
         UA_UInt32 /*monId*/, void* monContext, size_t nEventFields, UA_Variant* eventFields) {
    UaMonitoredItem* monItem = (UaMonitoredItem*)monContext;
    UaSubscription* sub = (UaSubscription*)subContext;
    if (monItem && sub) {
        monItem->EventNotification(nEventFields, eventFields);
    }
}

void UaMonitoredItem::DeleteMonitoredItemCallback
        (UA_Client* /*client*/, UA_UInt32 /*subId*/,
         void* subContext, UA_UInt32 /*monId*/, void* monContext) {

    UaMonitoredItem *monItem = (UaMonitoredItem*)monContext;
    UaSubscription *sub = (UaSubscription*)subContext;
    if (monItem && sub) {
        monItem->DeleteMonitoredItem();
    }
}

bool  UaMonitoredItem::Remove() {
    bool status =  false;
    if ((GetId() > 0) && _sub.GetOpcUaClient().GetClient() ) {
        status = UA_Client_MonitoredItems_deleteSingle(_sub.GetOpcUaClient().GetClient(), _sub.GetId(), GetId()) == UA_STATUSCODE_GOOD;
        //UA_MonitoredItemCreateResult_delete(&_result);
    }
    return status;
}

bool MonitoredItemDataChange::AddDataChange(UaNodeId& nodeId, UA_TimestampsToReturn timeStamps) {
    UA_MonitoredItemCreateRequest monRequest = UA_MonitoredItemCreateRequest_default(nodeId.GetNodeId());
    result = UA_Client_MonitoredItems_createDataChange(GetSubscription().GetOpcUaClient().GetClient(),
                                                       GetSubscription().GetId(),
                                                       timeStamps,
                                                       monRequest,
                                                       this,
                                                       DataChangeNotificationCallback,
                                                       DeleteMonitoredItemCallback);
    return result.statusCode == UA_STATUSCODE_GOOD;
}

bool MonitoredItemDataChange::AddDataChange(UaNodeId &nodeId, UA_TimestampsToReturn timeStamps, unsigned samplingInterval, bool discardOldest, unsigned queueSize) {
    UA_MonitoredItemCreateRequest monRequest = UA_MonitoredItemCreateRequest_default(nodeId.GetNodeId());
    monRequest.requestedParameters.samplingInterval = samplingInterval;
    monRequest.requestedParameters.discardOldest = discardOldest;
    monRequest.requestedParameters.queueSize = queueSize;
    // TODO set up filter for value changes
    //UA_DataChangeFilter filter;
    //monRequest.requestedParameters.filter.content.decoded.data =
    //monRequest.requestedParameters.filter.content.decoded.type = &UA_TYPES[UA_TYPES_DATACHANGEFILTER];

    result = UA_Client_MonitoredItems_createDataChange(GetSubscription().GetOpcUaClient().GetClient(),
                                                       GetSubscription().GetId(),
                                                       timeStamps,
                                                       monRequest,
                                                       this,
                                                       DataChangeNotificationCallback,
                                                       DeleteMonitoredItemCallback);
    return result.statusCode == UA_STATUSCODE_GOOD;
}

/*
bool Open62541::MonitoredItemEvent::addEvent(UaNodeId &n, EventFilterSelect *events, UA_TimestampsToReturn ts) {
    if (events) {
        //
        remove(); // delete any existing item
        //
        _events = events; // take ownership - events must be deleted after the item is removed
        MonitoredItemCreateRequest item;
        item = UA_MonitoredItemCreateRequest_default(n);

        item.get().itemToMonitor.nodeId = n;
        item.get().itemToMonitor.attributeId = UA_ATTRIBUTEID_EVENTNOTIFIER;
        item.get().monitoringMode = UA_MONITORINGMODE_REPORTING;

        item.get().requestedParameters.filter.encoding = UA_EXTENSIONOBJECT_DECODED;
        item.get().requestedParameters.filter.content.decoded.data = events->ref();
        item.get().requestedParameters.filter.content.decoded.type = &UA_TYPES[UA_TYPES_EVENTFILTER];

        _result = UA_Client_MonitoredItems_createEvent(subscription().client().client(),
                                                         subscription().id(),
                                                         ts,
                                                         item,
                                                         this,
                                                         eventNotificationCallback,
                                                         deleteMonitoredItemCallback);
        return _result.get().statusCode == UA_STATUSCODE_GOOD;
    }
    return false;
}*/