function varargout=web(varargin)
%WEB Open Web site or file in Web browser.
%   WEB opens an empty MATLAB Web browser.
%
%   WEB URL displays the page specified by URL in the MATLAB Web browser.
%   If URL is an external site, the page opens in your system browser. If
%   any MATLAB Web browsers are already open, it displays the page in the
%   browser that was used last. If URL is located inside the installed 
%   documentation, the page displays in the MATLAB Help browser instead of
%   the MATLAB Web browser.
%
%   The WEB command accepts a valid URL such as a web site address, a full 
%   path to a file, or a relative path to a file (using URL within the 
%   current folder if it exists there). 
%
%   WEB URL -NEW displays the page specified by URL in a new MATLAB Web
%   browser. This syntax does not apply when the page opens in your system 
%   browser.
%
%   WEB URL -NOTOOLBAR displays the page specified by URL in a MATLAB 
%   Web browser that does not include the toolbar and address field. If any
%   MATLAB Web browsers are already open, also use the -new option.
%   Otherwise, the page displays in the browser that was used last, 
%   regardless of its toolbar status.
%
%   WEB URL -NOADDRESSBOX displays the page specified by URL in a MATLAB
%   Web browser that does not include the address field. If any MATLAB Web
%   browsers are already open, also use the -new option. Otherwise the page
%   displays in the browser that was used last, regardless of its address
%   field status.
%
%   WEB URL -BROWSER displays the page specified by URL in your system 
%   Web browser. URL can be in any form that the browser supports. 
%   On Microsoft Windows and Apple Macintosh platforms, the system Web 
%   browser is determined by the operating system. On UNIX platforms, 
%   the default system Web browser for MATLAB is Mozilla Firefox. To 
%   specify a different browser, use MATLAB Web preferences.
%
%   STAT = WEB(...) returns the status of the WEB command in the
%   variable STAT. STAT = 0 indicates successful execution. STAT = 1
%   indicates that the browser was not found. STAT = 2 indicates that the
%   browser was found, but could not be launched.
%
%   [STAT, BROWSER] = WEB(...) returns the status, and a handle to the last
%   active browser. If the page opens in a system browser, the WEB command 
%   returns an empty handle.
%
%   [STAT, BROWSER, URL] = WEB(...) returns the status, a handle to the last
%   active browser, and the URL of the current location. If the page opens 
%   in a system browser, the WEB command returns an empty handle and URL.
%
%   Examples:
%      web https://www.mathworks.com 
%         loads the MathWorks Web site home page in your system browser. 
%      
%      web file:///disk/dir1/dir2/foo.html
%         opens the file foo.html in the MATLAB Web browser.
%
%      web mydir/myfile.html 
%         opens myfile.html in the MATLAB Web browser, where
%      mydir is in the current folder.
%
%      web(['file:///' which('foo.html')])
%         opens foo.html if the file is in a folder on the search path or
%         in the current folder for MATLAB.
%
%      web('text://<html><h1>Hello World</h1></html>') 
%         displays the HTML-formatted text Hello World.
%    
%      web('mydir/myfile.html', '-new', '-notoolbar') 
%         opens myfile.html in a new MATLAB Web
%         browser that does not include a toolbar or address field.
%
%      web file:///disk/dir1/foo.html -browser
%         opens the file foo.html in the system Web browser.
%
%      web mailto:email_address 
%         uses the system browser's default email application to send a
%         message to email_address.
%
%      [stat,h1]=web('mydir/myfile.html'); 
%         opens myfile.html in a MATLAB Web browser. Use close(h1) to
%         close the browser window.

%   Copyright 1984-2021 The MathWorks, Inc.

% Examine the inputs to see what options are selected.
[options, html_file] = examineInputs(varargin{:});

if nargout > 0
    varargout = {1 [] ''}; 
end

% Warn about depricated output arguments.
if nargout == 2
    displayWarningMessage(message('MATLAB:web:BrowserOuptputArgRemovedInFutureRelease'), ...
        options.showWarningInDialog);    
elseif nargout == 3
    displayWarningMessage(message('MATLAB:web:BrowserAndUrlOuptputArgsRemovedInFutureRelease'), ...
        options.showWarningInDialog);            
end

% Handle matlab: protocol by passing the command to evalin.
if startsWith(html_file, 'matlab:')
    evalin('caller', html_file(8:end));
    if nargout > 0
        varargout(1) = {0};
    end
    return
end

% Redirect links to old demo pages to corresponding Examples pages.
[redirect,mapfile,topic] = matlab.internal.help.checkForDemoRedirect(html_file);
if redirect
    helpview(mapfile,topic)
    if nargout > 0
        varargout(1) = {0};
    end
    return
end

% Redirect external links to the system browser based on preference.
options.isExternalPage = isExternalPage(html_file, options.isDeployed);
options.isSystemBrowserForExternalSites = isSystemBrowserForExternalSites();

if ~options.useSystemBrowser && options.isExternalPage && options.isSystemBrowserForExternalSites
    options.useSystemBrowser = 1;
end

if ~options.useSystemBrowser && usejava('mwt') && ~startsWith(html_file, 'mailto:')
    % If in Java environment, use the MATLAB web browser for everything
    % other than mailto.
    [activeBrowser, html_file] = openMatlabBrowser(html_file, options);
    if nargout > 0
        varargout = {0 activeBrowser html_file};
        if nargin > 0 && isstring(varargin{1})
            varargout{3} = string(varargout{3});
        end
    end
    logDDUXUIEvent(options, nargout);               
    return;
elseif ~usejava('mwt') && isHelpFile(html_file)
    displayWarningMessage(message('MATLAB:web:NoHelpBrowser'), ...
        options.showWarningInDialog);
    if nargout > 0 && isstring(varargin{1})
        varargout{3} = string(varargout{3});
    end
    return;
end

% Otherwise, use system web browser.

% If no URL is specified with system browser, complain and exit.
if isempty(html_file)
    displayWarningMessage(message('MATLAB:web:NoURL'),...
        options.showWarningInDialog);
    return
end

% We'll only issue a warning for a system error if we will not be 
% returning a status code.
options.warnOnSystemError = nargout == 0;

% open HTML file in system browser
if matlab.internal.web.isOnFileSystem(html_file)
    html_file = matlab.internal.language.introspective.removeDotsFromFilePath(html_file);
end

% Fix missing web protocol.
html_file = fixWebProtocol(html_file);
% Launch system browser.
stat = launchSystemBrowser(html_file, options);

if nargout > 0
    varargout(1) = {stat};
end

% When opening the system browser, only do the logging if the command completed
% successfully.
if (stat == 0)
    logDDUXUIEvent(options, nargout);
end

end

%--------------------------------------------------------------------------
function [options, html_file] = examineInputs(varargin)
% Initialize defaults.
options = struct;

% If running in deployed mode, use the system browser since the builtin
% web browser is not available.
options.isDeployed = isdeployed;
options.useSystemBrowser = options.isDeployed;
options.showWarningInDialog = 0;
options.useHelpBrowser = 0;
options.newBrowser = 0;
options.showToolbar = 1;
options.showAddressBox = 1;

html_file = '';

for i = 1:length(varargin)
    try
        argName = strip(varargin{i});
    catch e
        e.throwAsCaller;
    end
    switch argName
    case "-browser"
        options.useSystemBrowser = 1;
    case "-display"
        options.showWarningInDialog = 1;
    case "-helpbrowser"
        options.useHelpBrowser = 1;
    case "-new"
        options.newBrowser = 1;
    case "-notoolbar"
        options.showToolbar = 0;
    case "-noaddressbox"
        options.showAddressBox = 0;
    otherwise
        % assume this is the filename.
        html_file = char(argName);
    end
end
html_file = resolveUrl(html_file);
end

%--------------------------------------------------------------------------
function html_file = resolveUrl(html_file)
if ~isempty(html_file)
    if ~(startsWith(html_file, 'text://') || startsWith(html_file, 'http://'))
        % If the file is on MATLAB's search path, get the fully qualified
        % filename.
        fullpath = getWhich(html_file);
        if ~isempty(fullpath)
            if iscell(fullpath)
                for i = 1:length(fullpath)
                    if isfile(fullpath{i})
                        html_file = fullpath{i};
                        return;
                    end
                end
            elseif isfile(fullpath)
                % This means the file is on the path somewhere.
                html_file = fullpath;
            end
        else
            % If the file is referenced as a relative path, get the fully
            % qualified filename.
            fullpath = fullfile(pwd,html_file);
            if matlab.internal.web.isOnFileSystem(fullpath)
                html_file = fullpath;
            end
        end
    end
end
end

%--------------------------------------------------------------------------
function [activeBrowser, html_file] = openMatlabBrowser(html_file, options)

% Initialize the active browser.
activeBrowser = [];

% If no protocol specified, or an absolute/UNC pathname is not given,
% include explicit 'http:'.  Otherwise the web browser assumes 'file:'
if ~contains(html_file,':') && contains(html_file, '\\') && ~startsWith(html_file, '\\') && ~startsWith(html_file, '/')
    html_file = strcat('http://', html_file);
end

% If the file is not streaming text, use the help browser if and only if 
% the file is a help file. If the file is streaming text, respect the
% useHelpBrowser option.
if ~isempty(html_file) && ~startsWith(html_file, 'text://')
    options.useHelpBrowser = isHelpFile(html_file);
end

% The file should be displayed inside the help browser
if options.useHelpBrowser
    if startsWith(html_file, 'text://')
        com.mathworks.mlservices.MLHelpServices.setHtmlText(html_file(8:end));
    else
        com.mathworks.mlservices.MLHelpServices.setCurrentLocation(html_file);
    end
else
    activeBrowser = [];
    if ~options.newBrowser
        % User doesn't want a new browser, so find the active browser.
        activeBrowser = com.mathworks.mde.webbrowser.WebBrowser.getActiveBrowser;
    end
    if isempty(activeBrowser)
        % If there is no active browser, create a new one.
        activeBrowser = com.mathworks.mde.webbrowser.WebBrowser.createBrowser(options.showToolbar, options.showAddressBox);
    end
    
    if ~isempty(html_file)
        if startsWith(html_file, 'text://')
            activeBrowser.setHtmlText(html_file(8:end));
        else
            activeBrowser.setCurrentLocation(html_file);
        end                
    else
        html_file = char(activeBrowser.getCurrentLocation);
    end
end

end

%--------------------------------------------------------------------------

function stat = launchSystemBrowser(html_file, options)

try
    launcher = matlab.internal.web.SystemBrowserLauncher;
    [stat, msg] = openSystemBrowser(launcher, html_file);
catch ME
    stat = 1;
    msg = ME.message;
end
    
if stat ~= 0
    handleWarning(msg ,options.warnOnSystemError, options.showWarningInDialog);    
end

end

%--------------------------------------------------------------------------
function handleWarning(theMessage, warnOnSystemError, warnInDialog)
if warnOnSystemError
    displayWarningMessage(theMessage, warnInDialog);
end
end

%--------------------------------------------------------------------------
function displayWarningMessage(theMessage, warnInDialog)
if warnInDialog
    warndlg(getString(theMessage), getString(message('MATLAB:web:DialogTitleWarning')));
else
    warning(theMessage);
end
end

%--------------------------------------------------------------------------
function html_url = fixWebProtocol(html_file)
    if usejava('jvm')
        url_string = parseUrl(html_file);
        if (isWebProtocol(url_string))
            html_url = url_string;
        else
            html_url = html_file;
        end
    else
        html_url = html_file;
    end
end

%--------------------------------------------------------------------------
function url_string = parseUrl(html_file)
    try
        url = com.mathworks.html.Url.parse(html_file);            
        url_string = char(url.toString()); 
    catch
        url_string = html_file;
    end    
end

%--------------------------------------------------------------------------
function web_protocol = isWebProtocol(url_string)
    if startsWith(url_string, 'http://') || startsWith(url_string, 'https://')
        web_protocol = 1;
    else
        web_protocol = 0;
    end    
end

%--------------------------------------------------------------------------
function fullpath = getWhich(html_file)
    try
        fullpath = which(html_file,'-all');            
    catch
        fullpath = '';
    end    
end

function is_system_browser = isSystemBrowserForExternalSites()
    try
        is_system_browser = com.mathworks.mlwidgets.html.HTMLPrefs.isSystemBrowserForExternalSites().booleanValue();            
    catch
        is_system_browser = 0;
    end    
end

%--------------------------------------------------------------------------
function is_external_page = isExternalPage(html_file, deployed)
    is_external_page = 0;    
    if ~deployed
        try
            is_external_page = ~isStreamingText(html_file) && isExternalUrl(html_file) && ~(isViewingWebDoc() && isHelpFile(html_file));
        catch
            is_external_page = 0;
        end
    end        
end

function is_streaming_text = isStreamingText(html_file)
    is_streaming_text = startsWith(html_file, 'text://');
end

%--------------------------------------------------------------------------
function is_external_url = isExternalUrl(html_file)
    try        
        is_external_url = com.mathworks.mlwidgets.html.HTMLUtils.isExternalUrl(html_file);            
    catch
        is_external_url = 0;
    end    
end

%--------------------------------------------------------------------------
function is_viewing_web_doc = isViewingWebDoc()
    docLocation = com.mathworks.mlwidgets.help.HelpPrefs.getDocCenterLocationSilently();
    is_viewing_web_doc = strcmp(docLocation, 'WEB');
end

%--------------------------------------------------------------------------
function logDDUXUIEvent(options, nargout)
    if ~options.useHelpBrowser
        outputArgs = getOutputArgs(nargout);
        destinationString = getDestinationString(options.useSystemBrowser);
        com.mathworks.mlwidgets.html.ddux.DduxWebUiEventLogger.logUIEvent('web', destinationString, options.isExternalPage, outputArgs);
    end
end

%--------------------------------------------------------------------------
function destination_string = getDestinationString(useSystemBrowser)
    if useSystemBrowser
        destination_string = 'systembrowser';
    else
        destination_string = 'webbrowser';
    end        
end

%--------------------------------------------------------------------------
function output_args = getOutputArgs(nargout)
    switch nargout
        case 1
            output_args = "stat";  
        case 2
            output_args = ["stat"; "browser"];  
        case 3
            output_args = ["stat"; "browser"; "url"];  
        otherwise            
            output_args = [];
    end
end

%--------------------------------------------------------------------------
function help_file = isHelpFile(html_file)
    help_file = matlab.internal.help.isUnderDocroot(html_file) || matlab.internal.help.isConnectorHelpPage(html_file);
end
