//
// Created by magino on 27.5.19.
//

#ifndef S7VARIABLENODE_H
#define S7VARIABLENODE_H

#include "composite/INode.h"
#include "core/UaObjects.h"
#include <compositeBuilder/S7CsvDataBlock/S7CsvRowModel.h>

class S7VariableNode: public INode {
    S7CsvRowModel _row;
public:
    S7VariableNode(ICommunication& comm, MyUaServer& server, S7CsvRowModel& row): INode(comm, server), _row(row)  {}
    ~S7VariableNode() override = default;

    void* GetCommParam() override { return &_row; }
    UA_DataType GetUaDataType() const override  { return _row.uaDataType; };

    void AddOpcUaNode(UaNodeId& parent) override {
        UA_Byte access = UA_ACCESSLEVELMASK_READ;
        if (_row.writable)
            access |= UA_ACCESSLEVELMASK_WRITE;

        uaServer.AddVariableNode(_row.name,
                                 _row.name,
                                 _row.description,
                                 false,
                                 access,
                                 _row.uaDataType.typeIndex,
                                 UA_VALUERANK_SCALAR,
                                 0,
                                 nullptr,
                                 parent,
                                 instanceNodeId, // requested node id
                                 UaNodeId::HasComponent,
                                 UaNodeId::BaseDataVariableType,
                                 this);

        if(SetValueCallback(uaServer, instanceNodeId))
            UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "Added Value Callback to Node - %s.", &_row.name[0]);
    }

/*
    IS7Node* FindNode(const UaNodeId& uaNodeId) override {
        //if(UA_NodeId_equal(&nodeId, uaNodeId))
        //    return this;
        if(nodeIdd == uaNodeId)
            return this;
        else return nullptr;
    }
*/

    // request from opc ua -> to PLC (getting value from process)
    void ReadValue(UaNodeId &node, const UA_NumericRange* range, const UA_DataValue* value) override {
        UA_Variant val = comm.ReadValue(&_row);
        UA_Server_writeValue(uaServer.GetServer(), node.GetNodeId(), val);
    }
    // request from opc ua -> to PLC (writing to underlying process)
    void WriteValue(UaNodeId& nodeId, const UA_NumericRange* /*range*/, const UA_DataValue& value) override {
        comm.WriteValue(value.value, &_row);
    }
};

#endif //S7VARIABLENODE_H