% CustomSettingsPropDisp - base class implementing display functionality for all settings-backed objects
% This is very similar to parallel.internal.cluster.CustomPropDisp

% Copyright 2011-2020 The MathWorks, Inc.

classdef (Hidden) CustomSettingsPropDisp < handle
    methods ( Sealed ) % must be sealed to be invokable from Heterogeneous subclasses
        function disp( x )
            d = iGetDisplayer(x);
            d.doDisp( x );
        end

        function display( x, varargin ) %#ok<DISPLAY> we overload display
            d = iGetDisplayer(x);
            d.doDisplay( x, inputname(1), varargin{:} );
        end
    end

    methods ( Hidden )
        function [n, f] = hCustomizeDisplay( ~, ~ )
            n = {};
            f = {};
        end

        function propValues = hGetDisplayPropertiesNoError( obj, propNames )
            try
                propValues = obj.get( propNames );
            catch err %#ok<NASGU>
                % See if we have any better luck getting each prop individually,
                % otherwise just use the default values.
                propValues = cellfun( @(x) obj.getSingleDisplayPropertyNoError(x), ...
                    propNames, 'UniformOutput', false );
            end
        end
    end

    methods (Access = private)
        function v = getSingleDisplayPropertyNoError( obj, propName )
            v = '';
            try
                v = obj.get( propName );
            catch err %#ok<NASGU>
            end
        end
    end
end

% --------------------------------------------------------------------------
function d = iGetDisplayer( obj )
    persistent sDISP_MAP
    persistent sINVALID_DISP
    if isempty( sDISP_MAP )
        sDISP_MAP = containers.Map;
        sINVALID_DISP = parallel.internal.display.InvalidDisplayer();
    end
    key = class( obj );

    % Also handles empty obj.
    if ~isvalid( obj )
        d = sINVALID_DISP;
    elseif sDISP_MAP.isKey( key )
        d = sDISP_MAP( key );
    else
        d = iGetDisplayerFromClass( obj );
        sDISP_MAP( key ) = d;
    end
end

% --------------------------------------------------------------------------
function d = iGetDisplayerFromClass( obj )
    if isa( obj, 'parallel.Settings' )
        d = parallel.internal.settings.ParallelSettingsDisplayer( obj );
    elseif isa( obj, 'parallel.settings.Profile' )
        d = parallel.internal.settings.ProfileDisplayer( obj );
    elseif isa( obj, 'parallel.settings.ProjectComponent' )
        d = parallel.internal.settings.ProjectComponentDisplayer( obj );
    elseif isa( obj, 'parallel.settings.schedulerComponent.ThirdPartyCJS' )
        d = parallel.internal.settings.ThirdPartyCJSComponentDisplayer( obj );
    elseif isa( obj, 'parallel.settings.schedulerComponent.Local' )
        d = parallel.internal.settings.LocalSchedulerComponentDisplayer( obj );
    elseif isa( obj, 'parallel.settings.schedulerComponent.MJS' )
        d = parallel.internal.settings.MJSComponentDisplayer( obj );
    elseif isa( obj, 'parallel.settings.SchedulerComponent' )
        % NB SchedulerComponentDisplayer must come below the specific
        % scheduler component types.
        d = parallel.internal.settings.SchedulerComponentDisplayer( obj );
    else
        warning(message('parallel:settings:NoDisplayAvailable', class( obj )));
        d = struct( 'doDisp',    @(x,y) disp( x.get ), ...
                    'doDisplay', @(x,y) disp( x.get ) );
    end
end
