classdef RandomParameterSpace < multisim.design.internal.ParameterSpace
    %RANDOMPARAMETERSPACE Parameter space with 1 or more random parameters

    % Copyright 2022 The MathWorks, Inc.

    properties(Dependent)
        %RandomParameterSpace can only contain RandomParameters
        Parameters stats.internal.RandomParameter {mustBeVector}
    end
    properties(Access = public)
        NumSamples double {mustBeInteger, mustBePositive, mustBeScalarOrEmpty}
    end

    properties(Access = private)
        Parameters_ stats.internal.RandomParameter {mustBeVector} = stats.internal.RandomParameter.empty(1,0)
    end

    methods
        function obj = RandomParameterSpace(params,numsamples)
            arguments
                params stats.internal.RandomParameter = stats.internal.RandomParameter.empty(1,0)
                numsamples double {mustBeInteger, mustBePositive, mustBeScalarOrEmpty} = []
            end

            obj = setParameters(obj,params);
            obj.NumSamples = numsamples;
        end
        function obj = set.Parameters(obj,newValue)
            obj = setParameters(obj,newValue);
        end
        function params = get.Parameters(obj)
            params = getParameters(obj);
        end

        function sampler = createSampler(obj)
            if isempty(obj.NumSamples)
                error(message('stats:sensitivity:general:errRandomParameterSpace_createSampler_NumSamples'))
            end
            sampler = createSampler_(obj);
        end
    end

    %Allow the set/getParameters() methods to be overridden by subclasses,
    %e.g., quasi-random needs to override to keep correlation consistent
    %with the parameter list.
    methods(Access = protected)
        function obj = setParameters(obj,newValue)

            if isempty(newValue)
                obj.Parameters_ = newValue;
                return
            end

            %Make sure that the parameters are unique. 
            pTypes = [newValue.ParameterType];
            nP = numel(pTypes);
            if nP > 1
                ids(nP) = pTypes(nP).getUniqueID;
                for ct=1:nP-1
                    ids(ct) = pTypes(ct).getUniqueID;
                end
                if numel(ids) == numel(unique(ids))
                    obj.Parameters_ = newValue;
                else
                    error(message('stats:sensitivity:general:errRandomParameterSpace_UniqueParameters'))
                end
            else
                %Single parameter
                obj.Parameters_ = newValue;
            end
        end
        function params = getParameters(obj)
            params = obj.Parameters_;
        end
        function sampler = createSampler_(obj)
             sampler = stats.internal.sampler.RandomParameterSpace(obj);
        end
    end
end
