function varargout = unique(A, varargin)
%UNIQUE Set unique for codistributed array data.
%   C = UNIQUE(A)
%   [C,IA,IC] = UNIQUE(A)
%   [C,IA,IC] = UNIQUE(A,'rows')
%   [C,IA,IC] = UNIQUE(A,OCCURRENCE)
%   [C,IA,IC] = UNIQUE(A,'rows',OCCURRENCE)
%   [C,IA,IC] = UNIQUE(A,'stable')
%   [C,IA,IC] = UNIQUE(A,'rows','stable')
%   
%   Table and timetable inputs are not supported.
%   
%   See also UNIQUE, codistributed.


%   Copyright 2016-2023 The MathWorks, Inc.

% Gather optional flags.
varargin = distributedutil.CodistParser.gatherElements(varargin);
% Use the local function to check syntax and throw appropriate errors
distributedutil.validateSyntax(@unique, [{A}, varargin]);
% We don't support tables or timetables yet, so immediately error for these
if istabular(A)
    error(message('parallel:array:UnsupportedFunction', 'UNIQUE', underlyingType(A)));
end

varargout = cell(1, max(1, nargout));

if isscalar(A)
    % Scalar inputs are special cases not correctly handled by
    % in-memory flow-through, so a shortcut is used instead.
    [varargout{:}] = iUniqueScalar(A);
elseif iscellstr(A) %#ok<ISCLSTR>
    % Similarly cellstr inputs aren't handled by flow-through.
    [varargout{:}] = iUniqueCellstr(A, varargin{:});
else % Otherwise we flow-through in-memory implementation.
    [varargout{:}] = parallel.internal.array.callToolboxFunction(...
        "matlab/ops/unique", A, varargin{:});
end

% Post-process special case where A is empty by codistributing the outputs.
if isempty(A)
    varargout = cellfun(@codistributed, varargout, "UniformOutput", false);
end
end

function varargout = iUniqueScalar(A)
% Special case where A is a scalar.
varargout{1} = A;
if nargout >= 2
    varargout{2} = codistributed(1);
    if nargout == 3
        varargout{3} = varargout{2};
    end
end
end

function varargout = iUniqueCellstr(A, varargin)
% Special case where A is a cellstr. In this case we convert to string and
% call in-memory implementation.

% cellstr don't support "rows", a warning is thrown and the
% option is removed. distributedutil.validateSyntax deals with the
% warning but we need to remove "rows" from flags because string support
% it.
if nargin >= 2
    nonRowsFlags = ~cellfun(@(x) matlab.internal.math.partialMatch(x, "rows"), varargin);
    varargin = varargin(nonRowsFlags);
end

% Convert to string and call in-memory implementation.
varargout = cell(1, max(1, nargout));
[varargout{:}] = parallel.internal.array.callToolboxFunction(...
    "matlab/ops/unique", string(A), varargin{:});
varargout{1} = cellstr(varargout{1});
end
