function [msgType, lightnessPDU] = helperBLEMeshLightnessPDU(msgType, varargin)
%helperBLEMeshLightnessPDU Generate Bluetooth mesh lightness PDU
%   [MSGTYPE, LIGHTNESSPDU] = helperBLEMeshLightnessPDU(MSGTYPE, VARARGIN)
%   generates Bluetooth mesh lightness PDU, LIGHTNESSPDU and type of
%   message MSGTYPE, based on the specified inputs.
%
%   MSGTYPE is a character vector or a string scalar indicating the type of
%   message.
%
%   LIGHTNESSPDU is a column vector of decimal octets.
%
%   Signatures of different lightness messages are as follows:
%   1. Light lightness set, Light lightness set unacknowledged
%   If non-instantaneous state change, the signature is [MSGTYPE, 
%   LIGHTNESSPDU] = helperBLEMeshLightnessPDU(MSGTYPE, LIGHTNESS, TID, 
%   TRANSITIONTIMESTEPS, TRANSITIONTIMERESOLUTION, DELAY). If instantaneous
%   state change, the signature is [MSGTYPE, LIGHTNESSPDU] = 
%   helperBLEMeshLightnessPDU(MSGTYPE, LIGHTNESS, TID).
% 
%   2. Light lightness status
%   If state transition is in progress the signature is [MSGTYPE, 
%   LIGHTNESSPDU] = helperBLEMeshLightnessPDU(MSGTYPE, PRESENTLIGHTNESS, 
%   TARGETLIGHTNESS, REMAININGTIMESTEPS, REMAININGTIMERESOLUTION) otherwise
%   the signature is [MSGTYPE, LIGHTNESSPDU] = 
%   helperBLEMeshLightnessPDU(MSGTYPE, LIGHTNESS).
%   
%   LIGHTNESS, PRESENTLIGHTNESS, TARGETLIGHTNESS, TID, TRANSITIONTIMESTEPS,
%   TRANSITIONTIMERESOLUTION, DELAY, REMAININGTIMESTEPS,
%   REMAININGTIMERESOLUTION are integer values.
%
%   Copyright 2019 The MathWorks, Inc.

%#codegen

% Validate message type
validateattributes(msgType, {'string', 'char'}, {}, mfilename, 'msgType');

% Initialize
lightnessPDU = zeros(1, 0);

switch msgType        
    case {'Light lightness set', 'Light lightness set unacknowledged'}
        % Number of input arguments check
        narginchk(3, 6);
        
        % Validate lightness
        validateattributes(varargin{1}, {'numeric'}, {'scalar', 'integer', ...
            'nonnegative' '<=', 65535}, mfilename, 'LightLightness');
        
        % Validate transaction identifier
        validateattributes(varargin{2}, {'numeric'}, {'scalar', 'integer', ...
            'nonnegative', 'real'}, mfilename, 'TransactionId');
        
        % Lightness (2 octets)
        lightnessBin = de2bi(varargin{1}, 16);
        lightness = [bi2de(lightnessBin(1:8)); ...
            bi2de(lightnessBin(9:16))];
        
        % State change is non-instantaneous
        if (length(varargin) > 2)
             % Validate transition time steps
            validateattributes(varargin{3}, {'numeric'}, {'scalar', 'integer', ...
                '>=', 0, '<=', 62}, mfilename, 'TransitionTimeSteps');
            
            % Validate transition time resolution
            validateattributes(varargin{4}, {'numeric'}, {'scalar', 'integer', ...
                '>=', 0, '<=', 3}, mfilename, 'TransitionTimeResolution');
            
            % Validate delay
            validateattributes(varargin{5}, {'numeric'}, {'scalar', 'integer', ...
                '>=', 0, '<=', 255}, mfilename, 'Delay');
            
            % Transition time (1 octet)
            transitionTimeSteps = de2bi(varargin{3}, 6);
            transitionTimeResolution = de2bi(varargin{4}, 2);
            transitionTime = bi2de([transitionTimeSteps, ...
                transitionTimeResolution]);
            
            % Put it all together
            lightnessPDU = [lightness; varargin{2}; transitionTime; varargin{5}];
        else
            % Put it all together
            lightnessPDU = [lightness; varargin{2}];
        end
        
    case 'Light lightness status'
        % Number of input arguments check
        narginchk(2, 5);
        
        % Validate present lightness
        validateattributes(varargin{1}, {'numeric'}, {'scalar', 'integer', ...
            '>=', 0, '<=', 65535}, mfilename, 'LightLightness');
                
        % Present lightness (2 octets)
        lightnessBin = de2bi(varargin{1}, 16);
        lightness = [bi2de(lightnessBin(1:8)); ...
            bi2de(lightnessBin(9:16))];
        
        % State change is in progress
        if (length(varargin) > 1)
            % Validate target lightness
            validateattributes(varargin{1}, {'numeric'}, {'scalar', 'integer', ...
                '>=', 0, '<=', 65535}, mfilename, 'LightTargetLightness');
            
             % Validate remaining time steps
             validateattributes(varargin{3}, {'numeric'}, {'scalar', 'integer', ...
                '>=', 0, '<=', 62}, mfilename, 'RemainingTimeSteps');
            
            % Validate remaining time resolution
            validateattributes(varargin{4}, {'numeric'}, {'scalar', 'integer', ...
                '>=', 0, '<=', 3}, mfilename, 'RemainingTimeResolution');
        
            % Target lightness (2 octets)
            targetLightnessBin = de2bi(varargin{2}, 16);
            targetLightness = [bi2de(targetLightnessBin(1:8)); ...
                bi2de(targetLightnessBin(9:16))];
            
            % Remaining time to reach target state (1 octet)
            remainingTimeSteps = de2bi(varargin{3}, 6);
            remainingTimeResolution = de2bi(varargin{4}, 2);
            remainingTime = bi2de([remainingTimeSteps, ...
                remainingTimeResolution]);
            
            % Put it all together
            lightnessPDU = [lightness; targetLightness; remainingTime];
        else
            % Put it all together
            lightnessPDU = lightness;
        end
        
    otherwise
        fprintf("LightnessPDU: Given message type is not supported.\n");
end
end