classdef (Hidden) ModeSelectionData < mrtool.data.AbstractToolData
    % Mode Selection Data Class for Mode Selection Tool
    
    % Author(s): Suat Gumussoy
    % Copyright 2015 The MathWorks, Inc. 
    
    properties(Access = private, SetObservable = true, AbortSet = true)
        LowerCutoff
        UpperCutoff
    end
    methods (Access = public)
        %% Constructor
        function this = ModeSelectionData(Target,TargetList)
            this = this@mrtool.data.AbstractToolData(Target,TargetList); 
            setFrequencyCutoffs(this);
            setDirty(this,false);
        end
        function setToolTarget(this,ToolTarget)
            setTarget(this,ToolTarget);                        
        end        
        %% Update the tab with new target
        function update(this)
            setFrequencyCutoffs(this);
            computeReducedSystem(this); 
            notify(this,'FrequencyRangeChanged');
        end 
        %% Get/Set functions for data
        function setFrequencyCutoffs(this)
            Range = mrtool.util.setSelectorFrequencyRange(getTargetFrequencyRange(this));
            this.LowerCutoff = Range(1);
            this.UpperCutoff = Range(2);            
        end
        %% Mode Selection Settings
        function LowerCutoff = getLowerCutoff(this)
            LowerCutoff = this.LowerCutoff;
        end          
        function UpperCutoff = getUpperCutoff(this)
            UpperCutoff = this.UpperCutoff;
        end          
        function setLowerCutoff(this,LowerCutoff)
            if mrtool.data.ModeSelectionData.isCutoffValid(LowerCutoff)
                if LowerCutoff<getUpperCutoff(this)
                    if ~isequal(getLowerCutoff(this),LowerCutoff)
                        this.LowerCutoff = LowerCutoff;
                        computeReducedSystem(this);
                        notify(this,'FrequencyRangeChanged');
                    end
                else
                    error(message('Control:mrtool:MSErrorLowerCutoffSmaller'));                    
                end
            else
                error(message('Control:mrtool:MSErrorLowerCutoff'));
            end
        end
        function setUpperCutoff(this,UpperCutoff)
            if mrtool.data.ModeSelectionData.isCutoffValid(UpperCutoff)
                if UpperCutoff>getLowerCutoff(this)
                    if ~isequal(getUpperCutoff(this),UpperCutoff)                        
                        Ts = getTs(getTargetSystem(this));
                        % for discrete systems, if exceeds Nyquist range, sets to
                        % Nyquist frequency
                        if (Ts>0 && (UpperCutoff>pi/Ts))
                            error(message('Control:mrtool:MSErrorNyquistFrequencyDiscrete',num2str(pi/Ts,6)));
                            % REVISIT: add message to event managger for nyquist frequency
                        else
                            this.UpperCutoff = UpperCutoff;
                            computeReducedSystem(this);
                            notify(this,'FrequencyRangeChanged');
                        end
                    end
                else
                    error(message('Control:mrtool:MSErrorUpperCutoffLarger'));
                end
            else
                error(message('Control:mrtool:MSErrorUpperCutoff'));
            end
        end
        % Options
        function setOptions(this,Options)
            if nargin<2
               this.Options = freqsepOptions; 
            elseif isa(Options,'ltioptions.freqsep')
                if ~isequal(this.Options,Options)
                    this.Options = Options;
                    computeReducedSystem(this);
                end
            else
                error(message('Control:mrtool:MSErrorOptions'));
            end            
        end
        %% Load/Save Session
        function loadSessionToolData(this,SessionData)    
            this.LowerCutoff = SessionData.LowerCutoff;
            this.UpperCutoff = SessionData.UpperCutoff;
            this.Options = SessionData.Options; 
            setVisualizations(this,SessionData.Visualizations)
            computeReducedSystem(this,true);
        end        
        function SessionData = saveSessionToolData(this,SessionData)
            SessionData.ToolType = 'ModeSelection';
            SessionData.LowerCutoff = getLowerCutoff(this);
            SessionData.UpperCutoff = getUpperCutoff(this);
            SessionData.Options = getOptions(this);
        end                
    end
    methods (Access = protected)        
        %% Reduced System
        function ReducedSystem = localComputeReducedSystem(this) 
            TargetSystem = getTargetSystem(this);
            Options = getOptions(this);
            % truncate upper
            ReducedSystem = freqsep(TargetSystem,getUpperCutoff(this),Options);                                
            % truncate lower
            [~,ReducedSystem] = freqsep(ReducedSystem,getLowerCutoff(this),Options);
        end
    end
    methods (Static)
        function Result = isCutoffValid(Cutoff)
            Result = ~isempty(Cutoff) && (isnumeric(Cutoff) && isscalar(Cutoff) && isreal(Cutoff) ... 
                    && Cutoff>0 && Cutoff<Inf);
        end
    end
    methods(Hidden=true)
        function Text = generateMATLABCode(this)
            Text = cell(0,1);            
            Text = controllib.internal.codegen.appendMATLABCode(Text,['%% ' getString(message('Control:mrtool:CodegenMSTitle'))]); 
            SystemName = sprintf('System = %s;',ltipack.createVarName(getTargetName(this)));
            Text = controllib.internal.codegen.appendMATLABCode(Text,SystemName,[],getString(message('Control:mrtool:CodegenSystem')));
            Text = controllib.internal.codegen.appendMATLABCode(Text,getUpperCutoff(this),'UpperCutoffFrequency');
            Text = controllib.internal.codegen.appendMATLABCode(Text,getLowerCutoff(this),'LowerCutoffFrequency');
            Text = controllib.internal.codegen.appendMATLABCode(Text,' ');
            Text = mrtool.util.appendMATLABCodeForOptions(Text,getOptions(this));
            Text = controllib.internal.codegen.appendMATLABCode(Text,' ');
            Text = controllib.internal.codegen.appendMATLABCode(Text,['% ' getString(message('Control:mrtool:CodegenMSReduceCommand'))]);
            Text = controllib.internal.codegen.appendMATLABCode(Text,'ReducedSystem = freqsep(System,UpperCutoffFrequency,Options);');
            Text = controllib.internal.codegen.appendMATLABCode(Text,'[~,ReducedSystem] = freqsep(ReducedSystem,LowerCutoffFrequency,Options);');
            Text = controllib.internal.codegen.appendMATLABCode(Text,' ');
            Text = controllib.internal.codegen.appendMATLABCode(Text,['% ' getString(message('Control:mrtool:CodegenCreatePlot'))]);
            Text = controllib.internal.codegen.appendMATLABCode(Text,'bode(System,ReducedSystem);');
            controllib.internal.codegen.showGeneratedMATLABCode(Text,false);            
        end        
    end    
end