function cfg = LevelControlFrameDecoder(commandType, zclPayload)
%LEVELCONTROLFRAMEDECODER decode Level Control cluster library frames
% CFG = LEVELCONTROLFRAMEDECODER(ZCLCONFIG, ZCLPAYLOAD) decodes the ZigBee
% Cluster Library payload ZCLPAYLOAD for the command type COMMANDTYPE and
% outputs the corresponding Level Control cluster frame configuration to
% the object CFG.
%
%   See also zigbee.LevelControlFrameConfig, zigbee.LevelControlFrameGenerator.

% Copyright 2017-2023 The MathWorks, Inc.

% 0. Initializing configuration object
cfg = zigbee.LevelControlFrameConfig('CommandType', commandType);

% convert bytes to bits
if ~isempty(zclPayload)
  zclPayloadBin = zigbee.internal.bytes2bits(zclPayload);
  firstOctet = bit2int(zclPayloadBin(1:8)', 8, false);
end

switch commandType
  % Move to Level | Move to Level with OnOff
  case {'Move to Level', 'Move to Level (with On/Off)'}
    % 1. Level (1 octet)
    cfg.Level = firstOctet;

    % 2. Transition Time (2 octets)
    cfg.TransitionTime = bit2int(zclPayloadBin(9:24)', 16, false);

  % Move | Move with OnOff
  case {'Move', 'Move (with On/Off)'}
    % 1. Move Mode (1 octet)
    if firstOctet == 0
      cfg.MoveMode = 'Up';
    elseif firstOctet == 1
      cfg.MoveMode = 'Down';
    else
      warning(getString(message('lrwpan:ZigBee:ZCLInvalidLevelCtrlUpDownMode', 'Move mode')));
    end

    % 2. Rate (1 Octet)
    cfg.Rate = bit2int(zclPayloadBin(9:16)', 8, false);

  % Step | Step with OnOff
  case {'Step', 'Step (with On/Off)'}
    % 1. Step Mode (1 octet)
    if firstOctet == 0
      cfg.StepMode = 'Up';
    elseif firstOctet == 1
      cfg.StepMode = 'Down';
    else
      warning(getString(message('lrwpan:ZigBee:ZCLInvalidLevelCtrlUpDownMode', 'Step mode')));
    end

    % 2. Rate (1 Octet)
    cfg.StepSize = bit2int(zclPayloadBin(9:16)', 8, false);

    % 3. Transition Time (2 octets)
    cfg.TransitionTime = bit2int(zclPayloadBin(17:32)', 16, false);
end
