function writematrix(A, filename, varargin)
%WRITEMATRIX Write a matrix to a file.
%
%   WRITEMATRIX(A) writes the homogenous array A to a comma-delimited text
%   file. The file name is the workspace name of the homogenous array A,
%   appended with ".txt".
%
%   If WRITEMATRIX cannot construct the file name from the homogenous array
%   input, it writes to the file "matrix.txt".
%
%   WRITEMATRIX overwrites any existing file by default, but this behavior
%   can be changed to append or error using the "WriteMode" name-value pair.
%
%   WRITEMATRIX(A, FILENAME) writes the homogenous array A to the file
%   FILENAME as column-oriented data. WRITEMATRIX determines the file
%   format from its extension. The extension must be one of those listed
%   below.
%
%   FILENAME can be one of these:
%
%       - For local files, FILENAME can contain an absolute file name with a
%         file extension. FILENAME can also be a relative path to the current
%         folder, or to a folder on the MATLAB path.
%         For example, to export to a file in the current folder:
%
%            writematrix(A, "records.txt");
%
%       - For remote files, FILENAME must be a full path specified as a
%         uniform resource locator (URL). For example, to export a remote
%         file to Amazon S3, specify the full URL for the file:
%
%            writematrix(A, "s3://bucketname/path_to_file/records.txt");
%
%         For more information on accessing remote data, see "Work with
%         Remote Data" in the documentation.
%
%   WRITEMATRIX(A, FILENAME, "FileType", FILETYPE) specifies the file type,
%   where FILETYPE is one of "text" or "spreadsheet".
%
%   WRITEMATRIX writes data to different file types as follows:
%
%   Delimited text files:
%   ---------------------
%
%   The following extensions are recognized: .txt, .dat, .csv, .log,
%                                            .text, .dlm
%
%   WRITEMATRIX creates a column-oriented text file, i.e., each
%   column of each variable in A is written out as a column in the
%   file.
%
%   Use the following optional parameter name/value pairs to control
%   how data are written to a delimited text file:
%
%   "Delimiter"    - The delimiter used in the file. Can be any of " ",
%                    "\t", ",", ";", "|" or their corresponding names "space",
%                    "tab", "comma", "semi", or "bar". Default is ",".
%
%   "LineEnding"   - The characters to place as the end of a line.
%                    Defaults to "\r\n" on Windows and "\n" on Unix
%                    based platforms.
%
%   "QuoteStrings" - A flag which specifies when to quote output text.
%                    - "minimal" (default) Any text which contains
%                      the delimiter, line ending, or the double-quote
%                      character '"' will be quoted.
%                    - "all" All text, categorical, datetime, or
%                      duration variables will be quoted.
%                    - "none" No variables will be quoted.
%
%                    Quoted text will be surrounded by double-quote
%                    charcters (") and double-quote charcters already
%                    appearing in the data will be replaced with two
%                    double-quotes (i.e. ""). E.g. When quoted, 'a"b' will
%                    be written as '"a""b"'.
%
%   "DateLocale"   - The locale that WRITEMATRIX uses to create month and
%                    day names when writing datetimes to the file. LOCALE must
%                    be a character vector or scalar string in the form xx_YY.
%                    See the documentation for DATETIME for more information.
%
%   "Encoding"     - The encoding to use when creating the file.
%                    The default value is "UTF-8".
%
%   "WriteMode"    - Append to an existing file or overwrite an
%                    existing file:
%                    - "overwrite" - Overwrite the file, if it
%                                    exists. This is the default option.
%                    - "append"    - Append to the bottom of the file,
%                                    if it exists.
%
%   Spreadsheet files:
%   ------------------
%
%   The following extensions are recognized: .xls, .xlsx, .xlsb, .xlsm,
%                                            .xltx, .xltm
%
%   WRITEMATRIX creates a column-oriented spreadsheet file, i.e., each column
%   of each variable in A is written out as a column in the file.
%
%   Use the following optional parameter name/value pairs to control how data
%   are written to a spreadsheet file:
%
%   "DateLocale"     - The locale that writematrix uses to create month and day
%                      names when writing datetimes to the file. LOCALE must be
%                      a character vector or scalar string in the form xx_YY.
%                      Note: The "DateLocale" parameter value is ignored
%                      whenever dates can be written as Excel-formatted dates.
%
%   "Sheet"          - The sheet to write, specified the worksheet name, or a
%                      positive integer indicating the worksheet index.
%
%   "Range"          - A character vector or scalar string that specifies a
%                      rectangular portion of the worksheet to write, using the
%                      Excel A1 reference style.
%
%   "UseExcel"       - A logical value that specifies whether or not to create the
%                      spreadsheet file using Microsoft(R) Excel(R) for Windows(R).
%                      Set "UseExcel" to one of these values:
%                      - false - Does not open an instance of Microsoft Excel
%                                to write the file. This is the default setting.
%                                This setting may cause the data to be
%                                written differently for files with
%                                live updates (e.g. formula evaluation or plugins).
%                      - true  - Opens an instance of Microsoft Excel to write 
%                                the file on a Windows system with Excel installed.
%
%   "WriteMode"      - Perform an in-place write, append to an existing
%                      file or sheet, overwrite an existing file or
%                      sheet.
%                      - "inplace"        - In-place replacement of
%                                           the data in the sheet.
%                                           This is the default
%                                           option.
%                      - "overwritesheet" - If sheet exists,
%                                           overwrite contents of sheet.
%                      - "replacefile"    - Create a new file. Prior
%                                           contents of the file and 
%                                           all the sheets are removed.
%                      - "append"         - Append to the bottom of
%                                           the occupied range within
%                                           the sheet.
%
%   "AutoFitWidth"   - A logical value that specifies whether or not to change
%                      column width to automatically fit the contents. Defaults to true.
%
%   "PreserveFormat" - A logical value that specifies whether or not to preserve
%                      existing cell formatting. Defaults to true.
%
%   In some cases, WRITEMATRIX creates a file that does not represent A
%   exactly, as described below. If you use READMATRIX(FILENAME) to read that
%   file back in and create a new matrix, the result may not have exactly
%   the same format or contents as the original matrix.
%
%   *  WRITEMATRIX writes out numeric data using long g format, and
%      categorical or character data as unquoted text.
%   *  WRITEMATRIX writes out arrays that have more than two dimensions as two
%      dimensional arrays, with trailing dimensions collapsed.
%
%   See also READMATRIX, READCELL, WRITECELL

%   Copyright 2018-2023 The MathWorks, Inc.

import matlab.internal.datatypes.isScalarText
import matlab.io.internal.interface.isSupportedWriteMatrixType
import matlab.io.internal.interface.suggestWriteFunctionCorrection
import matlab.io.internal.interface.validators.validateWriteFunctionArgumentOrder

if nargin < 2
    matrixname = inputname(1);
    if isempty(matrixname)
        matrixname = "matrix";
    end
    filename = matrixname + ".txt";
else
    for i = 1:2:numel(varargin)
        n = strlength(varargin{i});
        if n > 5 && strncmpi(varargin{i},"WriteVariableNames",n)
            error(message("MATLAB:table:write:WriteVariableNamesNotSupported","WRITEMATRIX"));
        end
        if n > 5 && strncmpi(varargin{i},"WriteRowNames",n)
            error(message("MATLAB:table:write:WriteRowNamesNotSupported","WRITEMATRIX"));
        end
    end
end

% writematrix supports writing scalar chars and strings, so we cannot
% rely only on the fact that the first argument provided is scalar text
% in order to suggest an argument reordering. We also have to be sure
% that the second argument is not scalar text and is a matrix type that is
% supported for writing.
if ~isScalarText(filename) && isSupportedWriteMatrixType(filename) && isScalarText(A)
    validateWriteFunctionArgumentOrder(A, filename, "writematrix", "matrix", @isSupportedWriteMatrixType);
end

if ~isSupportedWriteMatrixType(A)
    suggestWriteFunctionCorrection(A, "writematrix");
end


% Error if odd number of arguments.
if nargin > 2 && mod(nargin, 2) ~= 0
    error(message("MATLAB:table:write:NoFileNameWithParams"));
end

try
    % writematrix does not support writing to XML files.
    supportedFileTypes = """text"", ""spreadsheet""";
    fileType = matlab.io.xml.internal.write.errorIfXML(filename, supportedFileTypes, varargin{:});

    if ischar(A);A = string(A);end
    T = table(A);
    writetable(T,filename,varargin{:},"WriteVariableNames",false);
catch ME
    if ME.identifier == "MATLAB:table:write:UnrecognizedFileType"
        error(message("MATLAB:table:write:SupportedFileTypes", fileType, supportedFileTypes));
    else
        throw(ME);
    end
end

end
