function out = comparisons_private(action,varargin)
% Access to private functionality required by the Comparison Tool.

%   Copyright 2009-2017 The MathWorks, Inc.

switch action
    case 'textdiff'
        % Call private function
        out = textdiff(varargin{:});
    case 'bindiff'
        % Call private function
        out = comparisons.internal.binary.compare(varargin{:});
    case 'matdiff'
        % Call private function
        out = matdiff(varargin{:});
    case 'matview'
        % Call private function
        matview(varargin{:});
    case 'newcomparison'
        com.mathworks.comparisons.main.ComparisonUtilities.startEmptyComparison;
    case 'comparefiles'
        i_compareFiles(varargin{:});
    case 'comparevars'
        % Returns a string indicating whether the specified inputs are equal.
        out = comparisons.internal.variablesEqual(varargin{1}, varargin{2});
    case 'vardiff'
        out = vardiff(varargin{:});
    case 'linediff'
        [line1,line2] = linediff(varargin{:});
        out = {line1,line2};
    case 'diffcode'
        [a, b, c] = diffcode(varargin{:});
        out = {a,b,c};
        
% These are callbacks from the ListComparison report
    case 'compare'
        com.mathworks.comparisons.compare.concr.ListComparisonUtilities.compareFiles(varargin{1},varargin{2});
    case 'view'
        com.mathworks.comparisons.compare.concr.ListComparisonUtilities.viewFile(varargin{1},varargin{2},varargin{3});
    case 'skip'
        com.mathworks.comparisons.compare.concr.ListComparisonUtilities.skipAsync(varargin{1});
    case 'cancel'
        com.mathworks.comparisons.compare.concr.ListComparisonUtilities.cancelAsync(varargin{1});

% These are callbacks from the MAT-file comparison report
    case 'varcomp'
        % The inputs are filename1,filename2,varname
        i_compareVariables(varargin{:});
    case 'varmerge'
        varmerge(varargin{:});
    case 'varcleanup'
        varcleanup(varargin{1});
        
% This is a callback from the Binary comparison report
    case 'bindiffrefresh'
        c = com.mathworks.comparisons.compare.concr.BinaryComparison.getComparison(varargin{1});
        if ~isempty(c)
            % Refresh this report
            c.doRefresh(true)
        else
            % The report wasn't created by an (open) BinaryComparison
            % instance.  It could be a TextComparison report which
            % encountered a binary file.
            c = com.mathworks.comparisons.compare.concr.TextComparison.getComparison(varargin{1});
            if ~isempty(c)
                % Yes.  Rerun the comparison, but using the "detailed
                % binary" option.
                c.doDetailedBinary;
            end
        end
        
% For testing purposes only.  Inputs are: function name, nargout, other
% arguments to be passed to private function
    case 'debug'
        out = cell(1,varargin{2});
        [out{:}] = feval(varargin{1},varargin{3:end});
        
    otherwise
        comparisons.internal.message('error', 'comparisons:comparisons:UnknownAction', action);
end

end

function i_compareFiles(f1,f2,type)
    if nargin<1
        % No files specified.
        com.mathworks.comparisons.main.ComparisonUtilities.startEmptyComparison;
        return;
    end
    f1 = java.io.File(comparisons.internal.resolvePath(f1));
    if nargin<2
        % Only one file specified.  This will show the source
        % selection dialog with one file already selected.
        com.mathworks.comparisons.main.ComparisonUtilities.startComparison(f1,[]);
        return;
    end
    f2 = java.io.File(comparisons.internal.resolvePath(f2));
    if nargin<3 || isempty(type)
        % By default, choose a comparison method automatically even if
        % there is a choice.
        autoselect = true;
    elseif ~isempty(type)
        % The third input is either the comparison type to use or a logical
        % value indicating whether or not we should select a comparison type
        % automatically.
        if ischar(type) || (isstring(type) && isscalar(type))
            type = char(type);
            % The user has specified a comparison type (via its a data type,
            % and we can register only one comparison type per data type).
            s1 = com.mathworks.comparisons.source.impl.LocalFileSource(f1,f1.getAbsolutePath());
            s2 = com.mathworks.comparisons.source.impl.LocalFileSource(f2,f2.getAbsolutePath());
            compatible_types = com.mathworks.comparisons.main.ComparisonTool.getInstance.getCompatibleComparisonTypes(s1,s2,[]);
            for i=0:compatible_types.size-1
                this_type = compatible_types.get(i);
                if strcmpi(this_type.getDataType.getName,type)
                    % Found the comparison type we need.
                    sel = com.mathworks.comparisons.selection.ComparisonSelection(s1,s2);
                    sel.setComparisonType(this_type);
                    % Run the comparison
                    com.mathworks.comparisons.main.ComparisonUtilities.startComparison(sel);
                    return;
                end
            end
            % The specified comparison type was not found in the list.
            comparisons.internal.message('error', 'comparisons:comparisons:UnknownComparisonType', type);
        else
            % Not a string.  Assume that it's a logical and that it specifies
            % whether we should automatically select a comparison method, or
            % prompt the user if multiple methods are available.
            autoselect = logical(type);
        end
    end
    try
        % This will throw an exception if the sources are of types which cannot
        % be compared with each other.
        com.mathworks.comparisons.main.ComparisonUtilities.startComparison(f1,f2,autoselect);
    catch E
        % The Java exception doesn't display tidily in MATLAB, so we need
        % to retrieve the message again and do the argument substitution
        % ourselves.
        if ~isempty(strfind(E.message,'NoSuitableComparisonTypeException'))
            msg = char(com.mathworks.comparisons.util.ResourceManager.getString(...
                'exception.nosuitablecomparisontype'));
            msg = strrep(msg,'{0}',char(f1.getAbsolutePath));
            msg = strrep(msg,'{1}',char(f2.getAbsolutePath));
            error('comparisons:comparisons:NoSuitableComparisonType','%s',msg);
        else
            rethrow(E);
        end
    end
end
        
function i_compareVariables(filename1, filename2, varname)
refname1 = comparisons.internal.loadVariable(filename1, varname, '_left');
refname2 = comparisons.internal.loadVariable(filename2, varname, '_right');
[~,f1] = fileparts(filename1);
[~,f2] = fileparts(filename2);
if ~strcmp(f1,f2)
    sourcename1 = [f1 '.' varname];
    sourcename2 = [f2 '.' varname];
else
    sourcename1 = [f1 '_left.' varname];
    sourcename2 = [f2 '_right.' varname];
end
vs1 = com.mathworks.comparisons.source.impl.VariableSource(sourcename1,...
    ['evalin(''base'',''' refname1 ''')'],...
    ['comparisons_private(''varcleanup'',''' refname1 ''')']);
vs2 = com.mathworks.comparisons.source.impl.VariableSource(sourcename2,...
    ['evalin(''base'',''' refname2 ''')'],...
    ['comparisons_private(''varcleanup'',''' refname2 ''')']);
com.mathworks.comparisons.main.ComparisonUtilities.startComparison(vs1,vs2,true)
end
