classdef SlHardwareConfigHelper < handle
%SlHardwareConfigHelper: utility class to manage hardware configuration
%                        diagnostics
%
%   This is an undocumented class. Its methods and properties are likely to
%   change without warning from one release to the next.

%   Copyright 2018-2020 The MathWorks, Inc.
    
    methods(Static)
        function checkWordSize(configInterface, isPIL, isReadOnly)
            % check native word size and throw helpful message
           
            % populate arguments for shared checkWordSize method
            hwSettingsActions = {'HWImplPane'};
            hwSettingsMsgString = '';
            enableLongLongActions = {'LongLong'};    
            enableLongLongMsgString = '';
            noWordSizeErrorId = 'PIL:pil:NoWordSizeMappingSimulink';
            
            function [componentName, hwPrefix] = getActionArgs
                % get the arguments required by fix-it actions
                componentName = configInterface.getCodeGenComponent;
                prodEqTarget = strcmp(configInterface.getParam('ProdEqTarget'), 'on');
                if prodEqTarget
                    hwPrefix = 'Prod';
                else
                    hwPrefix = 'Target';
                end
            end
            
            % call helper
            rtw.connectivity.ExtendedHardwareConfig.checkWordSize(configInterface, ...
                isPIL, ...
                isReadOnly, ...
                hwSettingsActions, ...
                hwSettingsMsgString, ...
                enableLongLongActions, ...
                enableLongLongMsgString, ...
                noWordSizeErrorId, ...
                @getActionArgs);
        end
        
        function throwWarningOrErrors(silHwImplValidationObj, isReadOnly)
            % THROWWARNINGORERRORS
            %
            if silHwImplValidationObj.IsPWS && ~isempty(silHwImplValidationObj.InvalidParams)
                % for PWS, warn about limitations that can lead to
                % unexpected numeric results
                infoStr = silHwImplValidationObj.createInfoStr(silHwImplValidationObj.HostVals, ...
                    silHwImplValidationObj.TargetVals, ...
                    silHwImplValidationObj.InvalidParams);
                componentName = silHwImplValidationObj.ComponentName;
                
                readOnlyActionIDs = {'HWImplDoc'};
                fullAccessActionIDs = {'HWImplPane'};
                dialog = coder.connectivity.AccessDependentDiagnostic(...
                'PIL:pil:HWImplPWSLimitations', ...
                    readOnlyActionIDs, ...
                    fullAccessActionIDs, ...
                    componentName, ...
                    infoStr);
                dialog.reportWarning(isReadOnly);
            else 
                % Throw any warnings
                if ~isempty(silHwImplValidationObj.InvalidParamsWithWarning)
                    isHardError = false;
                    infoStrForWarning = silHwImplValidationObj.createInfoStr(silHwImplValidationObj.HostWarningVals, ...
                        silHwImplValidationObj.TargetWarningVals, ...
                        silHwImplValidationObj.InvalidParamsWithWarning);
                    rtw.pil.SlHardwareConfigHelper.throwHWImplNotForHost(silHwImplValidationObj.ComponentName, ...
                        infoStrForWarning, ...
                        isHardError, ...
                        silHwImplValidationObj.IsERTTarget, ...
                        isReadOnly);
                end
                
                % Throw any hard errors
                if ~isempty(silHwImplValidationObj.InvalidParamsWithError)
                    isHardError = true;
                    infoStrForError = silHwImplValidationObj.createInfoStr(silHwImplValidationObj.HostErrorVals, ...
                        silHwImplValidationObj.TargetErrorVals, ...
                        silHwImplValidationObj.InvalidParamsWithError);
                    rtw.pil.SlHardwareConfigHelper.throwHWImplNotForHost(silHwImplValidationObj.ComponentName, ...
                        infoStrForError, ...
                        isHardError, ...
                        silHwImplValidationObj.IsERTTarget, ...
                        isReadOnly, ...
                        'EndianessNonFiniteError', silHwImplValidationObj.EndianessNonFiniteError);
                end
            end
        end
        
        function throwHWImplNotForHost(componentName, infoStr, isHardError, isERTTarget, isReadOnly, varargin)
            % utility function to throw the error for checkHostImplProps
            % and checkHostWordLengths
            
            % Process optional parameters
            p = inputParser;
            p.addParameter('EndianessNonFiniteError', false, @islogical);
            p.parse(varargin{:});
            
            % check for a subsystem build
            sourceSubsystem = coder.internal.SubsystemBuild.getSourceSubsysName;
            if ~isempty(sourceSubsystem)
                % update componentName to refer to the original model
                % containing the subsystem
                componentName = strtok(sourceSubsystem, '/');
            end
            
            % check for a protected model block build
            if isReadOnly
                [isProtected, fullMdlName] = slInternal(...
                    'getReferencedModelFileInformation', componentName);
                if isProtected
                    % it is not possible to apply changes to a protected model,
                    % therefore we only provide a message and doc link
                    diag = MSLException(...
                        message('PIL:pil:SILIncompatibleHardwareCharacteristicsProtected', ...
                        fullMdlName, infoStr));
                    throwAsCaller(diag);
                end
            end

            if isHardError
                % select the appropriate host prod hardware
                prodHW = rtw.pil.ModelBlockPIL.getHostProdHW; 
                % get the shared actions
                if isERTTarget
                    if rtw.pil.ModelBlockPIL.getPWSEnableLongLong(componentName)
                        pwsFixitId = {'PWSLongLong'};
                    else
                        pwsFixitId = {'PWS'};
                    end
                else
                    pwsFixitId = {};
                end
                sharedActionsIds = [pwsFixitId {'HostComputerProd'}];
                readOnlyActionIDs = {'HWImplDoc'};
                if p.Results.EndianessNonFiniteError
                    % Disable SupportNonFinite (option when PWS is off and the only
                    % incompatible parameter configuration is endianess)
                    sharedActionsIds = [{'NonFinite'} sharedActionsIds];
                    
                    diag = coder.connectivity.AccessDependentDiagnostic(...
                         'PIL:pil:SILIncompatibleNonFiniteHardwareCharacteristics', ...
                             readOnlyActionIDs, ...
                             sharedActionsIds, ...W
                             componentName, ...
                             infoStr, prodHW);
                else
                    
                    diag = coder.connectivity.AccessDependentDiagnostic(...
                         'PIL:pil:SILIncompatibleHardwareCharacteristics', ...
                            readOnlyActionIDs, ...
                            sharedActionsIds, ... 
                            componentName, ...
                            infoStr, prodHW);
                end
                diag.throw(isReadOnly);
            else
                diag = MSLException(...
                    message('PIL:pil:SILWarningHardwareCharacteristics', ...
                        componentName, ...
                        infoStr));
                sldiagviewer.reportWarning(diag);
            end
        end
    end
end
