function GroupsFrame = GroupsFrameGenerator(cfg)
%GROUPSFRAMEGENERATOR Generate frames of the Groups ZigBee cluster
% GROUPSFRAME = GROUPSFRAMEGENERATOR(CFG) generates the Groups cluster
% frame GROUPSFRAME corresponding to the configuration object CFG.
%
% See also zigbee.GroupsFrameConfig, zigbee.GroupsFrameDecoder.

% Copyright 2017-2023 The MathWorks, Inc.

switch cfg.CommandType
  % Add group command
  case 'Add group'
    % 1. Group ID (2 octets)
    groupID = int2bit(hex2dec(cfg.GroupID), 16, false);

    % 2. Group name string length (1 octet)
    nameLen = int2bit(numel(cfg.GroupName), 8, false);

    % 3. Group Name (String)
    if nameLen == 0
      groupName = [];
    else
      groupName = int2bit(uint8(cfg.GroupName(:)), 8, false);
    end
    
    % 4. Putting it all together:
    GroupsFrame = [groupID; nameLen; groupName];

  % View group command
  case 'View group'
    % 1. Group ID (2 octets)
    GroupsFrame = int2bit(hex2dec(cfg.GroupID), 16, false);

  % Get group membership command
  case 'Get group membership'
    groupList = cfg.GroupList;

    % 1. Group count (1 octet)
    groupCountDec = size(groupList, 1);
    groupCount = int2bit(groupCountDec, 8, false);

    % 2. Group list ((groupCount * 2) octets)
    groupIDsList = zeros(groupCountDec*2*8, 1);
    for i = 1:16:groupCountDec*16
      groupIDsList(i:i+15) = int2bit(hex2dec(groupList(ceil(i/16), :)), 16, false);
    end

    % 3. Putting it all together:
    GroupsFrame = [groupCount; groupIDsList];

  % Remove group command
  case 'Remove group'
    % 1. Group ID (2 octets)
    GroupsFrame = int2bit(hex2dec(cfg.GroupID), 16, false);

  % Remove all groups command
  case 'Remove all groups'
    % Remove all groups doesn't contain any Payload
    GroupsFrame = [];

  % Add group if identifying command
  case 'Add group if identifying'
    % 1. Group ID (2 octets)
    groupID = int2bit(hex2dec(cfg.GroupID), 16, false);

    % 2. Group name string length (1 octet)
    nameLen = int2bit(numel(cfg.GroupName), 8, false);

    % 3. Group Name (String)
    if nameLen == 0
      groupName = [];
    else
      groupName = int2bit(uint8(cfg.GroupName(:)), 8, false);
    end

    % 4. Putting it all together:
    GroupsFrame = [groupID; nameLen; groupName];

  % Add group response command
  case 'Add group response'
    % 1. Status (1 octet)
    status = generateStatus(cfg);

    % 2. Group ID (2 octets)
    groupID = int2bit(hex2dec(cfg.GroupID), 16, false);

    % 3. Putting it all together:
    GroupsFrame = [status; groupID];

  % View group response command
  case 'View group response'
    % 1. Status (1 octet)
    status = generateStatus(cfg);

    % 2. Group ID (2 octets)
    groupID = int2bit(hex2dec(cfg.GroupID), 16, false);

    % 3. Group name string length (1 octet)
    nameLen = int2bit(numel(cfg.GroupName), 8, false);

    % 4. Group Name (String)
    if nameLen == 0
      groupName = [];
    else
      groupName = int2bit(uint8(cfg.GroupName(:)), 8, false);
    end

    % 5. Putting it all together:
    GroupsFrame = [status; groupID; nameLen; groupName];

  % Get group membership response command
  case 'Get group membership response'
    groupList = cfg.GroupList;

    % 1. Capacity (1 octet)
    capacity = int2bit(cfg.Capacity, 8, false);

    % 2. Group count (1 octet)
    groupCountDec = size(groupList, 1);
    groupCount = int2bit(groupCountDec, 8, false);

    % 3. Group IDs list ((groupCount * 2) octets)
    groupIDsList = zeros(groupCountDec*2*8, 1);
    for i = 1:16:groupCountDec*16
      groupIDsList(i:i+15) = int2bit(hex2dec(groupList(ceil(i/16), :)), 16, false);
    end

    % 4. Putting it all together:
    GroupsFrame = [capacity; groupCount; groupIDsList];

  % Remove group response command
  case 'Remove group response'
    % 1. Status (1 octet)
    status = generateStatus(cfg);

    % 2. Group ID (2 octets)
    groupID = int2bit(hex2dec(cfg.GroupID), 16, false);

    % 3. Putting it all together:
    GroupsFrame = [status; groupID];
end
% Convert bits to bytes:
if ~isempty(GroupsFrame)
  GroupsFrame = zigbee.internal.bits2bytes(GroupsFrame);
end
end

function status = generateStatus(cfg)
switch cfg.Status
  case 'Success'
    status = int2bit(hex2dec('00'), 8, false);
  case 'Duplicate exists'
    status = int2bit(hex2dec('8A'), 8, false);
  case 'No space'
    status = int2bit(hex2dec('89'), 8, false);
  case 'Not found'
    status = int2bit(hex2dec('8B'), 8, false);
end
end