classdef CSDParameterSpec < modelpack.ParameterSpec
    %modelpack.CSDParameterSpec class
    %   modelpack.CSDParameterSpec extends modelpack.ParameterSpec.
    %

%   Copyright 2023 The MathWorks, Inc.

    %    modelpack.CSDParameterSpec properties:
    %       Description - Property is of type 'ustring'
    %       Name - Property is of type 'string'  (read only)
    %       InitialValue - Property is of type 'MATLAB array'
    %       Known - Property is of type 'MATLAB array'
    %       Minimum - Property is of type 'MATLAB array'
    %       Maximum - Property is of type 'MATLAB array'
    %       TypicalValue - Property is of type 'MATLAB array'
    %       Format - Property is of type 'double'  (read only)
    %       FormatOptions - Property is of type 'string vector'  (read only)
    %       Listeners - Property is of type 'handle vector'
    %
    %    modelpack.CSDParameterSpec methods:
    %       copy -  method to make a copy of this object
    %       setFormat -  method to set the format of a SISOTOOL parameter spec object
    %       setName - Sets the name of the parameter.


    properties (GetAccess=protected, Transient, SetObservable)
        %LISTENERS Property is of type 'handle vector'
        Listeners = [];
    end

    properties (SetAccess=protected, SetObservable)
        %FORMAT Property is of type 'double'  (read only)
        Format = 1;
        %FORMATOPTIONS Property is of type 'string vector'  (read only)
        FormatOptions = { '' };
    end


    methods  % constructor block
        function this = CSDParameterSpec(ID, FormatOptions)
            % CSDParameterSpec  constructor for CSD parameter specification object
            %
            % h = modelpack.CSDParameterSpec(ID, [FormatOptions])
            %
            % Input:
            %    ID            - a CSD Parameter ID object
            %    FormatOptions - optional cell array specifying formats for this spec
            %

            % Create object

            % No argument constructor call
            ni = nargin;
            if (ni == 0)
                return
            end

            if (ni < 1) || ~isa(ID, 'modelpack.CSDParameterID')
                error(message('SLControllib:modelpack:errArgumentType','ID','modelpack.CSDParameterID'))
            end

            % Set invariant properties
            this.setID(ID); %Sets the name property
            this.Version = 1.0;

            %Set passed arguments
            if ni >=  2
                this.FormatOptions = FormatOptions;
            end


        end  % CSDParameterSpec

    end  % constructor block

    methods
        function set.Format(obj,value)
            % DataType = 'double'
            validateattributes(value,{'numeric'}, {'scalar'},'','Format')
            value = double(value); %  convert to double
            obj.Format = value;
        end

        function set.FormatOptions(obj,value)
            % DataType = 'string vector'
            % no cell string checks yet'
            obj.FormatOptions = value;
        end

        function set.Listeners(obj,value)
            % DataType = 'handle vector'
            validateattributes(value,{'handle'}, {'vector'},'','Listeners')
            obj.Listeners = value;
        end

    end   % set and get functions

    methods  % public methods
        function newObj = copy(this)
            % COPY  method to make a copy of this object
            %

            for ct=numel(this):-1:1
                newObj(ct) = modelpack.CSDParameterSpec;
                newObj(ct).ID                  = this(ct).ID;
                newObj(ct).Name                = this(ct).Name;
                newObj(ct).Dimension           = this(ct).Dimension;  %This must get copied before values are set
                newObj(ct).isDimensionEditable = this(ct).isDimensionEditable;
                newObj(ct).Format              = this(ct).Format;
                newObj(ct).FormatOptions       = this(ct).FormatOptions;
                newObj(ct).InitialValue        = this(ct).InitialValue;
                newObj(ct).TypicalValue        = this(ct).TypicalValue;
                newObj(ct).Minimum             = this(ct).Minimum;
                newObj(ct).Maximum             = this(ct).Maximum;
                newObj(ct).Known               = this(ct).Known;
            end
        end  % copy

        function setFormat(this,Model,newFormat)
            % SETFORMAT  method to set the format of a SISOTOOL parameter spec object
            %
            % this.setFormat(Model,newFormat)
            %
            % Inputs:
            %   Model     - a modelpack.CSDModel object for the SISOTOOL model containing
            %               the parameter
            %   newFormat - a numerical index or string giving the new parameter format,
            %               valid formats can be found from the 'FormatOptions' property, i.e.,
            %               this.FormatOptions
            %

            nFormatOptions = numel(this.FormatOptions);
            if ischar(newFormat)
                newFormat = find(strcmp(newFormat,this.FormatOptions));
                if isempty(newFormat), newFormat = inf; end
            end
            if nFormatOptions > 1 && newFormat <= nFormatOptions
                %Have valid new format
                if isa(Model,'ctrlguis.csdesignerapp.data.architectures.internal.PZGroup')
                    %PZGroup object
                    this.Minimum      = Model.convertValue(this.Minimum,this.Format,newFormat);
                    this.Maximum      = Model.convertValue(this.Maximum,this.Format,newFormat);
                    this.InitialValue = Model.convertValue(this.InitialValue,this.Format,newFormat);
                    this.TypicalValue = Model.convertValue(this.TypicalValue,this.Format,newFormat);
                    this.Format       = newFormat;
                elseif isa(Model,'ctrlguis.csdesignerapp.data.architectures.internal.TunableBlock')
                    %Tuned block gain object
                    this.Minimum      = Model.convertGainValue(this.Minimum,this.Format,newFormat);
                    this.Maximum      = Model.convertGainValue(this.Maximum,this.Format,newFormat);
                    this.InitialValue = Model.convertGainValue(this.InitialValue,this.Format,newFormat);
                    this.TypicalValue = Model.convertGainValue(this.TypicalValue,this.Format,newFormat);
                    this.Format       = newFormat;
                else
                    %Model api object
                    Model.convertValue(this,newFormat);
                end
            end
        end  % setFormat

        function this = setName(this, name)
            % SETNAME Sets the name of the parameter.

            % Type checking
            if ~ischar(name)
                error(message('SLControllib:modelpack:InvalidStringArgument', ...
                    'NAME', 'setName' ));
            end

            if strcmp(this.getID.getName,name)
                this.Name = name;
            else
                error(message('SLControllib:modelpack:stErrorParameterSubsref'))
            end

            this.setDimensions(this.getID.getDimensions) %Also initializes property sizes

        end  % setName

    end  % public methods

end  % classdef

% LocalWords:  FORMATOPTIONS ctrlguis csdesignerapp PZ
