function varargout = commblkSampleRateMatch(blkH, action, varargin)
    % Mask initialization function for the Sample-Rate Match block

    %   Copyright 2022 The MathWorks, Inc.

    switch action
        case 'Init'
            % Mask initialization

            [inputSampleRate, outputLength, outputSampleRateOption, outputSampleRate] = deal(varargin{:});

            validateattributes(inputSampleRate, "double", {"finite", "positive", "vector", ...
                "numel", 2}, "", "Input sample rate");
            validateattributes(outputLength, "double", ["scalar", "positive", "integer"], ...
                "", "Output samples per frame");

            if strcmp(outputSampleRateOption, 'Auto')
                maskObj = Simulink.Mask.get(blkH);
                outputSampleRateComputed = maskObj.getDialogControl('OutputSampleRateComputed');
                outputSampleRate = max(inputSampleRate);
                outputSampleRateComputed.Prompt = sprintf('Output sample rate (Hz): %0.5g', outputSampleRate);
            else
                validateattributes(outputSampleRate, "double", {"finite", "scalar", "positive", ...
                    ">=", max(inputSampleRate)}, "", "Output sample rate");
            end

            [L, M] = rat(outputSampleRate./inputSampleRate, 0);
            tooLargeL = (L > 5.6e6);
            if any(tooLargeL)
                inSR = inputSampleRate(tooLargeL);
                error(message('comm:SampleRateMatch:NeedTooMuchMemory', ...
                    inSR(1), outputSampleRate));
            end
            varargout = {L, M};

        case 'OutputSampleRateOption'
            % Mask parameter visibilities

            vis = {'on', 'on', 'on', 'on'};
            maskObj = Simulink.Mask.get(blkH);
            outputSampleRateComputed = maskObj.getDialogControl('OutputSampleRateComputed');

            if strcmpi(get_param(blkH, 'OutputSampleRateOption'), 'Auto')
                vis{4} = 'off';
                wsVar = get_param(blkH, 'MaskWSVariables');
                idx = strcmp({wsVar.Name}, 'InputSampleRate');
                inputSampleRate = wsVar(idx).Value;
                outputSampleRate = max(inputSampleRate);
                outputSampleRateComputed.Prompt = sprintf('Output sample rate (Hz): %0.5g', outputSampleRate);
                outputSampleRateComputed.Visible = 'on';
            else
                outputSampleRateComputed.Visible = 'off';
            end
            set_param(blkH, 'MaskVisibilities', vis);
            varargout = {};

        case 'StartFcn'
            % StartFcn callback

            blkName = getfullname(blkH);
            wsVar = get_param(blkH, 'MaskWSVariables');
            idx = strcmp({wsVar.Name}, 'InputSampleRate');
            inputSampleRates = wsVar(idx).Value;
            
            % Port#1
            in1 = [blkName '/In1'];
            framePeriod1 = get_param(in1, 'CompiledSampleTime');
            fPeriod1 = framePeriod1(1);
            dims = get_param(in1, 'CompiledPortDimensions');
            fLength1 = dims.Outport(2);
            actualInputSampleRate1 = fLength1/fPeriod1;
            err = abs(actualInputSampleRate1 - inputSampleRates(1))/actualInputSampleRate1;
            if (err > sqrt(eps))
                MSLDiagnostic(message('comm:shared:inputSampleRateMismatch', ...
                    blkName, inputSampleRates(1), actualInputSampleRate1)).reportAsWarning();
            end            
            % Port#2
            in2 = [blkName '/In2'];
            framePeriod2 = get_param(in2, 'CompiledSampleTime');
            fPeriod2 = framePeriod2(1);
            dims = get_param(in2, 'CompiledPortDimensions');
            fLength2 = dims.Outport(2);
            actualInputSampleRate2 = fLength2/fPeriod2;
            err = abs(actualInputSampleRate2 - inputSampleRates(2))/actualInputSampleRate2;
            if (err > sqrt(eps))
                MSLDiagnostic(message('comm:shared:inputSampleRateMismatch', ...
                    blkName, inputSampleRates(2), actualInputSampleRate2)).reportAsWarning();
            end

            varargout = {};

        otherwise
            varargout = {};
    end
end
