function cfg = MessagingFrameDecoder(commandType, zclPayload)
%MessagingFrameDecoder Decode Smart Energy frames for the Messaging cluster
%   CFG = zigbee.MessagingFrameDecoder(COMMANDTYPE, ZCLPAYLOAD) decodes the
%   ZigBee Smart Energy frame of the Messaging cluster ZCLPAYLOAD and
%   outputs the corresponding configuration object CFG.
%
%   See also zigbee.MessagingFrameConfig, zigbee.MessagingFrameGenerator.

%   Copyright 2017-2023 The MathWorks, Inc.

% convert bytes to bits
if ~isempty(zclPayload)
  zclPayloadBin = zigbee.internal.bytes2bits(zclPayload);
end

% 0. Initialize:
cfg = zigbee.MessagingFrameConfig;

switch commandType
  case 'Display Message'
    % 1. Message Id
    cfg.MessageID = bit2int(zclPayloadBin(1:4*8)', 4*8, false);
    
    % 2. Message control
    cfg = decodeMessageControl(cfg, zclPayloadBin(1+4*8:5*8));
    
    % 3. Start time
%     cfg.StartTime = bit2int(zclPayloadBin(1+5*8:9*8)', 4*8, false);
%   Only zero values supported
    
    % 4. Duration in minutes
    cfg.Duration = bit2int(zclPayloadBin(1+9*8:11*8)', 2*8, false);
    
    % 5. Message    
    lengthOfTheMessage = bit2int(zclPayloadBin(1+11*8:12*8)', 8, false);
    if (lengthOfTheMessage ~= 0)
      cfg.Message = zigbee.internal.decodeLabel(zclPayloadBin(1+12*8:end));      
    end

    
  case 'Cancel Message'
    % 1. Command type
    cfg.CommandType = 'Cancel Message';
    
    % 2. Message Id
    cfg.MessageID = bit2int(zclPayloadBin(1:4*8)', 4*8, false);
    
    % 3. Message control
    cfg = decodeMessageControl(cfg, zclPayloadBin(1+4*8:end));
    
  case 'Get Last Message'
    % 1. Command type
    cfg.CommandType = 'Get Last Message';
    
  case 'Message Confirmation'
    % 1. Command type
    cfg.CommandType = 'Message Confirmation';
    
    % 2. Message Id
    cfg.MessageID = bit2int(zclPayloadBin(1:4*8)', 4*8, false);
    
    % 3. Confirmation time
    cfg.ConfirmationTime = bit2int(zclPayloadBin(1+4*8 : 8*8)', 4*8, false);
    
  otherwise
    error(message('lrwpan:ZigBee:ZCLInvalidValue', 'Command type'));
end
end

function cfg = decodeMessageControl(cfg, messageControl)

% 1. Transmission type
transmission = bit2int(messageControl(1:2)', 2, false);

switch transmission
  case 0
    cfg.TransmissionType = 'Normal Transmission Only';
  case 1
    cfg.TransmissionType = 'Normal and Inter-PAN Transmission';
  case 2
    cfg.TransmissionType = 'Inter-PAN Transmission Only';
  otherwise
    error(message('lrwpan:ZigBee:ZCLInvalidValue', 'Transmission type'));
end

% 2. Priority type
priority = bit2int(messageControl(3:4)', 2, false);

switch priority
  case 0
    cfg. Priority = 'Low';
  case 1
    cfg. Priority = 'Medium';
  case 2
    cfg. Priority = 'High';
  case 3
    cfg. Priority = 'Critical';
end

% 3. Message confirmation
cfg.MessageConfirmation = logical(messageControl(8));

end
