function serialPortValue = serialPortValueCallback(hCS, varargin)
% SERIALPORTVALUECALLBACK Value callback for serial port parameter in PIL
% and external mode in configuration parameters

% Copyright 2020-2022 The MathWorks, Inc.

setSerialFlag = 0;

if codertarget.target.isCoderTarget(hCS)
    hardwareBoard = codertarget.data.getParameterValue(hCS, 'TargetHardware');
    CPUValue = '';
    % Combine CPU information for hardwareBoard entry for the
    % specified targets
    data = codertarget.data.getParameterValue(hCS, 'Runtime');
    if codertarget.data.isValidParameter(hCS, 'ESB.ProcessingUnit')  
        data = codertarget.data.getParameterValue(hCS, 'ESB.ProcessingUnit');
        if contains(data, 'CPU1')
            CPUValue = 'CPU1';
        elseif contains(data, 'CPU2')
            CPUValue = 'CPU2';
        elseif contains(data, 'Cortex')
            CPUValue = 'ARM';
        else 
            CPUValue = 'CPU1'; %Processing Unit = None. Keeping default CPU1
        end
    end
        
    serialPortValue = codertarget.tic2000.internal.getSerialPortPreferences(hardwareBoard, CPUValue);
    
    if nargin == 2
        serialPortList = codertarget.registry.serialPortEntriesCallback('actual');
        if strcmpi(varargin{1},'ValidateExtMode') || ...
                strcmpi(varargin{1},'ValidatePIL') || ...
                strcmpi(varargin{1},'PILCOMPort') ||...
                strcmpi(varargin{1},'SimulinkIO_COMPort')
            modelName = get_param(hCS.getModel, 'Name');
            % Get the updated list
            if isempty(serialPortList)
                interactiveError(varargin{1}, modelName);
            else
                if isempty(serialPortValue)
                    % New serial port preference does not exists
                    if ispref('MathWorks_Embedded_IDE_Link_PIL_Preferences','COMPort') ...
                            && (strcmpi(varargin{1},'ValidatePIL') ...
                            || strcmpi(varargin{1},'PILCOMPort')...
                            || strcmpi(varargin{1},'SimulinkIO_COMPort'))
                        % Import the value from MathWorks_Embedded_IDE_Link_PIL_Preferences
                        % set for PIL
                        serialPortValue = getpref('MathWorks_Embedded_IDE_Link_PIL_Preferences','COMPort');
                        setSerialFlag = 1;
                        if isempty(find(strcmp(serialPortList, serialPortValue), 1))
                            interactiveError(varargin{1}, modelName);
                            setSerialFlag = 0;
                        end
                        rmpref('MathWorks_Embedded_IDE_Link_PIL_Preferences');
                        warning(message('TIC2000:codegen:IdelinkPILPrefrenceNotSupported'));
                    elseif codertarget.data.isValidParameter(hCS,'ExtModeCOMPort') ...
                            && strcmpi(varargin{1},'ValidateExtMode')
                        % If valid External mode COM port was saved with External mode
                        % in Model
                        serialPortValue = codertarget.data.getParameterValue(hCS, 'ExtModeCOMPort');
                        setSerialFlag = 1;
                        if isempty(find(strcmp(serialPortList, serialPortValue), 1))
                            interactiveError(varargin{1},modelName);
                            setSerialFlag = 0;
                        end
                    else
                        %Pick one of the value from the list which is
                        %current default setting in configuration parameter
                        %as well
                        serialPortValue = serialPortList{end};
                        setSerialFlag = 1;
                    end
                else
                    if isempty(find(strcmp(serialPortList, serialPortValue), 1))
                        % The preference set is incorrect, throw error
                        interactiveError(varargin{1}, modelName);
                    else
                        if ispref('MathWorks_Embedded_IDE_Link_PIL_Preferences','COMPort') ...
                                && (strcmpi(varargin{1},'ValidatePIL') ...
                                || strcmpi(varargin{1},'PILCOMPort')...
                                || strcmpi(varargin{1},'SimulinkIO_COMPort'))
                            rmpref('MathWorks_Embedded_IDE_Link_PIL_Preferences');
                            warning(message('TIC2000:codegen:IdelinkPILPrefrenceNotSupported'));
                        end
                    end
                end
            end
            if setSerialFlag == 1
                % Set the preferences for hardware board as it was updated.
                codertarget.tic2000.setSerialPortPreferences(hardwareBoard, CPUValue, serialPortValue);
            end
        elseif strcmpi(varargin{1}, 'ExtModeCOMPort')
            if isempty(serialPortValue)
                if codertarget.data.isValidParameter(hCS,'ExtModeCOMPort')
                    serialPortValue = codertarget.data.getParameterValue(hCS, 'ExtModeCOMPort');
                else
                    serialPortValue =  serialPortList{end};
                end
                % The preference set is empty, update it to default value
                codertarget.tic2000.setSerialPortPreferences(hardwareBoard, CPUValue, serialPortValue);
            end
            if ispc
                serialPortValue = strrep(serialPortValue, 'COM', '');
            else
                serialPortValue = sprintf('''%s''', serialPortValue);
            end
        end
    elseif nargin == 1
        % Get the updated list
        serialPortList = codertarget.registry.serialPortEntriesCallback;
        if isempty(serialPortValue) || isempty(find(strcmp(serialPortList, serialPortValue), 1))
            % If new serial port preference does not exists of wrong value
            % set in preferences pick a default value. Setting this value
            % in preferences will be done during CS refresh, External mode
            % or PIL run
            serialPortValue = serialPortList{end};
        end
    end
end
end

function interactiveError(type, modelName)
if strcmpi(type, 'ValidateExtMode')
    msg = message('TIC2000:codegen:SerialPreferencesIncorrectWarning', modelName);
    sldiagviewer.reportWarning(msg.getString,'MessageId',msg.Identifier);
elseif strcmpi(type, 'PILCOMPort')
    msg = message('TIC2000:codegen:SerialPreferencesIncorrectErrorPIL');
    err = MSLException([], msg);
    throw(err);
elseif strcmpi(type, 'SimulinkIO_COMPort')
    msg = message('TIC2000:codegen:SerialPreferencesIncorrectErrorSimulinkIO');
    err = MSLException([], msg);
    throw(err);
else
    disableError = 'No';
    if ispref('MathWorksTIC2000Preferences', 'disableSerialPortErrorforPIL')
        disableError = getpref('MathWorksTIC2000Preferences','disableSerialPortErrorforPIL');
    end
    if strcmpi(disableError, 'No')
        msg = message('TIC2000:codegen:SerialPreferencesIncorrectError', modelName);
        err = MSLException([], msg);
        throw(err);
    end
end
end
