function [macAddr, nodeId] = edcaNodeInfo(opType, nodeID, varargin)
%edcaNodeInfo Performs get or set operation for MAC address of the given
% node
%
%   MACADDR = edcaNodeInfo(OPTYPE, NODEID) performs the operation specified
%   by the OPTYPE on the node with the given NODEID.
%
%   [~, NODEID] = edcaNodeInfo(2, NODEID, MACADDR) returns the node ID of
%   the node with the given MAC address, MACADDR.
%
%   If the OPTYPE is specified as
%      a) 0 - A MAC address is assigned to the node and returns it in
%      MACADDR
%
%      b) 1 - Returns MAC address of the node in MACADDR
%
%      c) 2 - Returns the node ID of node with MAC address given in
%      VARARGIN in NODEID
%
%   NODEID is the ID of the node.
%
%   MACADDR is a decimal vector with 6 elements, representing the 6 octets
%   of the MAC address in decimal format.

%   Copyright 2019 The MathWorks, Inc. 

% Holds each node information(i.e., node id and MAC address) in the
% simulation
persistent nodeInfo;
% Keep the count of number of nodes in the simulation.
persistent nodeIdCounter;
% Initialize nodeInfo structure
if isempty(nodeInfo)
    s.id = 0;
    s.macAddr = [0 0 0 0 0 0];
    % Maximum number of nodes creation in a model is restricted to 250. Any
    % changes to maxNumberOfNodes variable value needs to be carried to the
    % maxNumberOfNodes variable in the dcfUpdateStats function.
    maxNumberOfNodes = 250;
    nodeInfo = repmat(s, maxNumberOfNodes, 1);
end
% Initialize nodeIdCount to zero
if isempty(nodeIdCounter)
    nodeIdCounter = 0;
end

% First byte of MAC address contains the information about MAC address
% type. All MAC addresses that are locally managed should set Bit-1 (second
% bit from LSB) of the first byte to 1. Set it to 0 to use globally unique
% (OUI enforced) MAC addresses. This function assigns MAC addresses that
% are locally administrated.
macAddrByte1 = 2;

% Assign default value to output variable
macAddr = [macAddrByte1 0 0 0 0 0];

% Switch to an operation type that is selected
switch(opType)
    case 0 % Assign MAC address
        % If MAC address of a node is all zeros, assign unique MAC address
        % to it. Otherwise, returns already assigned MAC address.
        if nodeInfo(nodeID).id == 0
            % Increment nodeIdCounter by 1
            nodeIdCounter = nodeIdCounter +1;
            % Store nodeId in nodeInfo array
            nodeInfo(nodeID).id = nodeID;
            % Generate a random MAC address and store it in nodeInfo array
            nodeInfo(nodeID).macAddr = [macAddrByte1 hex2dec(reshape(dec2hex(nodeID, 10), 2, 5)')'];
        end
        macAddr = nodeInfo(nodeID).macAddr;
    case 1 % Return MAC address of the node
        % Find and return MAC address of a node using nodeId
        if (nodeID <= nodeIdCounter) && (nodeID > 0)
            macAddr = nodeInfo(nodeID).macAddr;
            
        % Broad cast Node ID
        elseif nodeID == 65535 
            macAddr = [255 255 255 255 255 255];
        end
    case 2 % Returns Node ID corresponding to the given MAC address
        macAddrDec = hex2dec((reshape(varargin{1}, 2, [])'))';
        % Get MAC address in binary format excluding first byte
        macAddrBinary = (reshape(de2bi(macAddrDec(2:end), 'left-msb')', 1, []));
        nodeId = bi2de(macAddrBinary, 'left-msb');
end
