classdef (Hidden, Sealed) PluginHelpers
% PLUGINHELPERS Class to aid in the management of target creation plugins
% for creation of target objects.

%   Copyright 2020-2022 The MathWorks, Inc.
    
    properties (Constant)
        Service = targetframework.internal.plugins.creation.createTargetCreationPluginService()
        RegisteredPlugins = target.internal.PluginHelpers.Service.RegisteredPlugins
    end
    
    methods (Static)

        % Function to retrieve all plugins for published classes.
        function pluginNames = getPublishedTargetPlugins()

            pluginNames = {target.internal.PluginHelpers.RegisteredPlugins.TargetClass};

            % Remove classes that are hidden, or for which no MATLAB
            % wrappers exist.
            metaClasses = arrayfun(@(x) meta.class.fromName("target." + x), pluginNames, UniformOutput = false);
            locRemove = cellfun(@(x) isempty(x) || x.Hidden, metaClasses);

            pluginNames(locRemove) = [];
        end

        % Function to retrieve all plugins that implement a specific target
        % class.
        function targetPlugins = getSpecificPlugins(className)
            arguments
                className {mustBeTextScalar}
            end
            
            targetPlugins = target.internal.PluginHelpers.RegisteredPlugins(cellfun(@(x) isequal(x, className), ...
                {target.internal.PluginHelpers.RegisteredPlugins.TargetClass}));
        end
        
        % Function to retrieve the properties for tab-completion when a
        % user selects a class for which a plugin exists.
        function amendedProperties = getAmendedProperties(className, otherProperties)
            arguments
                className {mustBeTextScalar}
                otherProperties (1, :) string
            end
            
            % Get class properties. In case all plugins are excluded,
            % these are the properties that will be suggested to the user.
            amendedProperties = target.internal.ClassHelpers.getClassSettableProperties(className);
            
            locRemove = ismember(otherProperties, [amendedProperties, {'Copy'}, {'IDPrefix'}]);
            otherProperties(locRemove) = [];
            
            % Get plugins and remove those that do not match properties
            % that have already been input.
            plugins = target.internal.PluginHelpers.getSpecificPlugins(className);
            
            if ~isempty(otherProperties) && all(otherProperties ~= "")
                
                locRemove = arrayfun(@(x) ~any(ismember(vertcat(x.RequiredNameValues, x.OptionalNameValues), otherProperties)), plugins);
                plugins(locRemove) = [];
            end
            
            % Get plugin properties.
            if ~isempty(plugins)
                
                pluginProperties = vertcat(plugins.RequiredNameValues, plugins.OptionalNameValues);
                
                % Remove properties set by plugin.
                assignedProperties = plugins.AssignedProperties;
                
                locRemove = ismember(amendedProperties, assignedProperties);
                amendedProperties(locRemove) = [];
                
                % Amend plugin properties.
                amendedProperties = vertcat(amendedProperties(:), pluginProperties(:))';
            end
        end
    end
end
