classdef ScenesFrameConfig < matlab.mixin.CustomDisplay
%SCENESFRAMECONFIG Configuration for frames of the Scenes ZigBee cluster
% FRAMECONFIG = SCENESFRAMECONFIG creates a configuration object for frames
% of the Scenes ZigBee cluster.
%
% FRAMECONFIG = SCENESFRAMECONFIG(Name, Value) creates a ZigBee Scenes
% Cluster frame configuration object with the specified property Name set
% to the specified Value. You can specify additional name-value pair
% arguments in any order as (Name1, Value1, ..., NameN, ValueN).
%
% ScenesFrameConfig properties:
%
% CommandType         - Command type
% GroupID             - Group identifier
% SceneID             - Scene identifier
% TransitionTime      - Time to change state to requested scene
% SceneName           - Scene name
% ExtensionFieldSets  - Extension field sets
% Status              - Status of Add/View/Remove/Store/Get/Copy Scene commands
% CopyAllScenes       - Option to copy all scenes
% GroupIDFrom         - Originating Group ID in Copy Scene command
% GroupIDTo           - Destination Group ID in Copy Scene command
% SceneIDFrom         - Originating Scene ID in Copy Scene command
% SceneIDTo           - Destination Scene ID in Copy Scene command
% Capacity            - Number of free scene slots
% SceneList           - List of scene identifiers
%
% See also zigbee.ScenesFrameGenerator, zigbee.ScenesFrameDecoder.

% Copyright 2017-2023 The MathWorks, Inc.

properties
  %CommandType Command type
  % Specify CommandType as one of  'Add Scene' | 'View Scene' |
  % 'Remove Scene' | 'Remove All Scenes' | 'Store Scene' |
  % 'Recall Scene' | 'Get Scene Membership' | 'Enhanced Add Scene' |
  % 'Enhanced View Scene' | 'Copy Scene' | 'Add Scene Response' |
  % 'View Scene Response' | 'Remove Scene Response' | 'Remove All Scenes
  % Response' | 'Store Scene Response' | 'Enhanced View Scene Response' |
  % 'Get Scene Membership Response' | 'Enhanced Add Scene Response' |
  %  'Copy Scene Response'. The default is 'Add Scene'.
  CommandType = 'Add Scene';

  %Status Status of Add/View/Remove/Store/Get/Copy Scene commands
  % Specify Status as one of 'Success' | 'No space' | 'Invalid field' |
  % 'Not found'. The default is 'Success'.
  Status = 'Success';
  
  %GroupID Group identifier
  % Specify GroupID as a 4-character hexadecimal vector expressing the
  % 16-bit group ID. The default is '0000'.
  GroupID = '0000';

  %SceneID Scene identifier
  % Specify SceneID as a 2-character hexadecimal vector expressing the
  % 8-bit scene ID. The default is '00'.
  SceneID = '00';

  %TransitionTime Time to change state to requested scene
  % Specify TransitionTime as a scalar non-negative integer lesser than
  % 2^16. If CommandType is set to 'Enhanced Add Scene' or 'Enhanced View
  % Scene Response', then TransitionTime is specified in deciseconds (i.e.,
  % tenths of a second); otherwise it specified in seconds.  The default is 1.
  TransitionTime = 1;

  %SceneName Scene name
  % Specify SceneName as a character vector expressing the scene name.
  % The default is ''.
  SceneName = '';
  
  %ExtensionFieldSets Extension field sets
  % Specify ExtensionFieldSets as Structure with fields ClusterID, Length
  % and ExtensionValues. ClusterID must be a 4-character hexadecimal vector
  % expressing the 16-bit cluster ID. Length must be a scalar integer
  % between 0 and 255 (inclusive). ExtensionValues must be an Nx2 matrix;
  % each row contains a 2-character (8-bit) hexadecimal value.
  ExtensionFieldSets = struct('ClusterID', 'FFFF', ...
                              'Length', 0, ...
                              'ExtensionValues', '');

  %CopyAllScenes Option to copy all scenes
  % Specify CopyAllScenes as a scalar logical. This property applies when
  % CommandType is set to 'Copy Scene'. If true, all scenes are copied. The
  % default is false.
  CopyAllScenes = false;
  
  %GroupIDFrom Originating Group ID in Copy Scene command
  % Specify GroupIDFrom as a 4-character hexadecimal vector expressing the
  % 16-bit group ID. The default is '0000'.
  GroupIDFrom = '0000';

  %GroupIDTo Destination Group ID in Copy Scene command
  % Specify GroupIDTo as a 4-character hexadecimal vector expressing the
  % 16-bit group ID. The default is '0000'.
  GroupIDTo = '0000';

  %SceneIDFrom Originating Scene ID in Copy Scene command
  % Specify SceneIDFrom as a 2-character hexadecimal vector expressing the
  % 8-bit scene ID. The default is '00'.
  SceneIDFrom = '00';

  %SceneIDTo Destination Scene ID in Copy Scene command
  % Specify SceneIDTo as a 2-character hexadecimal vector expressing the
  % 8-bit scene ID. The default is '00'.
  SceneIDTo = '00';
  
  %Capacity Number of free scene slots
  % Specify Capacity as a scalar non-negative integer lesser than 256. The
  % default is 0.
  Capacity = 0;

  %GroupList List of scene identifiers
  % Specify SceneList as an Nx2 array; each row must be a 2-character hexadecimal
  % vector expressing the 8-bit Scene ID. The default is [].
  SceneList = [];
end

properties (Dependent)
	%SceneCount Size of SceneList
  % The number of scenes in the SceneList property.
  SceneCount = 0;
end

properties(Constant, Hidden)
  CommandTypeValues = {'Add Scene', 'View Scene', 'Remove Scene', 'Remove All Scenes', ...
              'Store Scene', 'Recall Scene', 'Get Scene Membership', 'Enhanced Add Scene', ...
              'Enhanced View Scene', 'Copy Scene', 'Add Scene Response', ...
              'View Scene Response', 'Remove Scene Response', ...
              'Remove All Scenes Response', 'Store Scene Response', ...
              'Get Scene Membership Response', 'Enhanced Add Scene Response', ...
              'Enhanced View Scene Response', 'Copy Scene Response'};
  StatusValues = {'Success', 'No space', 'Invalid field', 'Not found'};
end

methods
  function obj = ScenesFrameConfig(varargin)
    % Apply constructor name value pairs:
    for i = 1:2:nargin
      obj.(varargin{i}) = varargin{i+1};
    end
  end

  % For auto-completion:
  function v = set(obj, prop)
    v = obj.([prop, 'Values']);
  end

  function obj = set.CommandType(obj, value)
    obj.CommandType = validatestring(value, obj.CommandTypeValues, '', 'CommandType');
  end

  function obj = set.GroupID(obj, value)
    value = convertStringsToChars(value);
    validateattributes(value, {'char'}, {'row', 'numel', 4}, '', 'GroupID');
    obj.GroupID = value;
  end

  function obj = set.SceneID(obj, value)
    value = convertStringsToChars(value);
    validateattributes(value, {'char'}, {'row', 'numel', 2}, '', 'SceneID');
    obj.SceneID = value;
  end

  function obj = set.TransitionTime(obj, value)
    validateattributes(value, {'numeric'}, {'scalar', 'integer', 'nonnegative', 'real', '<', 65536}, '', 'TransitionTime');
    obj.TransitionTime = value;
  end

  function obj = set.SceneName(obj, value)
    value = convertStringsToChars(value);
    validateattributes(value, {'char'}, {'row'}, '', 'SceneName');
    if numel(obj.SceneName) > 16
      error(getString(message('lrwpan:ZigBee:ZCLNameLengthExceeded', 'Scene name')));
    end
    obj.SceneName = value;
  end

  function obj = set.CopyAllScenes(obj, value)
    validateattributes(value, {'logical'}, {'scalar'}, '', 'CopyAllScenes');
    obj.CopyAllScenes = value;
  end

  function obj = set.Status(obj, value)
    obj.Status = validatestring(value, obj.StatusValues, '', 'Status');
  end

  function obj = get.SceneCount(obj)
    obj.SceneCount = size(obj.SceneList, 1);
  end

  function obj = set.SceneList(obj, value)
    value = convertStringsToChars(value);  
    validateattributes(value, {'char'}, {'2d', 'ncols', 2}, '', 'SceneList');
    obj.SceneList = value;
  end

  function obj = set.Capacity(obj, value)
    validateattributes(value, {'numeric'}, {'scalar', 'integer', 'nonnegative', 'real', '<', 256}, '', 'Capacity');
    obj.Capacity = value;
  end

  function obj = set.GroupIDFrom(obj, value)
    value = convertStringsToChars(value);
    validateattributes(value, {'char'}, {'row', 'numel', 4}, '', 'GroupIDFrom');
    obj.GroupIDFrom = value;
  end

  function obj = set.GroupIDTo(obj, value)
    value = convertStringsToChars(value);
    validateattributes(value, {'char'}, {'row', 'numel', 4}, '', 'GroupIDTo');
    obj.GroupIDTo = value;
  end

  function obj = set.SceneIDFrom(obj, value)
    value = convertStringsToChars(value);
    validateattributes(value, {'char'}, {'row', 'numel', 2}, '', 'SceneIDFrom');
    obj.SceneIDFrom = value;
  end

  function obj = set.SceneIDTo(obj, value)
    value = convertStringsToChars(value);
    validateattributes(value, {'char'}, {'row', 'numel', 2}, '', 'SceneIDTo');
    obj.SceneIDTo = value;
    end

  function obj = set.ExtensionFieldSets(obj, value)
    for i = 1:numel(value)
      value(i).ClusterID = convertStringsToChars(value(i).ClusterID);
      value(i).ExtensionValues = convertStringsToChars(value(i).ExtensionValues);
      validateattributes(value(i).ClusterID, {'char'}, {'row', 'numel', 4}, '', 'ExtensionFieldSets.ClusterID');
      validateattributes(value(i).Length, {'numeric'}, {'scalar', 'integer', 'nonnegative', 'real', '<', 256}, '', 'ExtensionFieldSets.Length');
      validateattributes(value(i).ExtensionValues, {'char'}, {'2d', 'ncols', 2, 'nrows', value(i).Length}, '', 'ExtensionFieldSets.ExtensionValues');
    end
    obj.ExtensionFieldSets = value;
  end
end

methods (Access = protected)
  function groups = getPropertyGroups(obj)
    propList  = properties(obj);
    activeIdx1 = true(size(propList));

    for n = 1:numel(propList)
      if  isInactiveProperty(obj, propList{n})
        activeIdx1(n) = false;
      end
    end
    groups = matlab.mixin.util.PropertyGroup(propList(activeIdx1));
  end

  function flag = isInactiveProperty(obj, prop)
    flag = false;
    if strcmp(prop, 'GroupID')
      flag = any(strcmp(obj.CommandType, {'Copy Scene', 'Copy Scene Response'}));
      
    elseif strcmp(prop, 'SceneID')
      flag = any(strcmp(obj.CommandType, {'Remove All Scenes','Remove All Scenes Response' , ...
        'Get Scene Membership', 'Get Scene Membership Response', 'Copy Scene', 'Copy Scene Response'}));

    elseif strcmp(prop, 'TransitionTime')
      flag = ~any(strcmp(obj.CommandType, {'Add Scene', 'Enhanced Add Scene', 'View Scene Response', ...
          'Enhanced View Scene Response'}));        
      if any(strcmp(obj.CommandType, {'View Scene Response', 'Enhanced View Scene Response'})) == 1
        flag = strcmp(obj.Status, 'Success');
      end
      
    elseif any(strcmp(prop, {'SceneName', 'ExtensionFieldSets'}))
      
      flag = ~any(strcmp(obj.CommandType, {'Add Scene', 'Enhanced Add Scene', 'View Scene Response', ...
                                      'Enhanced View Scene Response'}));
      if any(strcmp(obj.CommandType, {'View Scene Response', 'Enhanced View Scene Response'}))
        flag = strcmp(obj.Status, 'Success');            
      end
      
    elseif strcmp(prop, 'CopyAllScenes')
      flag = ~strcmp(obj.CommandType, 'Copy Scene');
        
    elseif any(strcmp(prop, {'GroupIDFrom', 'SceneIDFrom'}))
      flag = ~any(strcmp(obj.CommandType, {'Copy Scene', 'Copy Scene Response'}));
      
    elseif any(strcmp(prop, {'GroupIDTo', 'SceneIDTo'}))
      flag = ~strcmp(obj.CommandType, 'Copy Scene');
      
    elseif strcmp(prop, 'Capacity')
      flag = ~strcmp(obj.CommandType, 'Get Scene Membership Response');
      
    elseif any(strcmp(prop, {'SceneCount', 'SceneList'}))
      flag = ~(strcmp(obj.CommandType, 'Get Scene Membership Response') && strcmp(obj.Status, 'Success')) ;
      
    elseif strcmp(prop, 'Status')
      flag = ~contains(obj.CommandType, 'Response'); % shows only in Response commands
    end
  end
end

end
