function publish(inputfile,outputfile,varargin)
% publish  Publish m-file or model file to PDF.
%
% Syntax
% =======
%
%     latex.publish(INPUTFILE)
%     latex.publish(INPUTFILE,OUTPUTFILE,...)
%
% Input arguments
% ================
%
% * `INPUTFILE` [ char | cellstr ] - Input file name; can be either an
% m-file, a model file, or a cellstr combining a number of them.
%
% * `OUTPUTFILE` [ char ] - Output file name; if not specified, it will be
% derived from the input file (with a pdf extension).
%
% Options
% ========
%
% --General options
%
% * `'cleanup='` [ *`true`* | `false` ] - Delete all temporary files
% (LaTeX and eps) at the end.
%
% * `'closeAll='` [ *`true`* | `false` ] - Close all figure windows at the
% end.
%
% * `'display='` [ *`true`* | `false` ] - Display pdflatex compiler report.
%
% * `'evalCode='` [ *`true`* | `false` ] - Evaluate code when publishing the
% file; the option is only available with m-files.
%
% * `'useNewFigure='` [ `true` | *`false`* ] - Open a new figure window for each
% graph plotted.
%
% --Content-related options
%
% * `'author='` [ char | *empty* ] - Author that will be included on the
% title page.
%
% * `'date='` [ char | *'\today' ] - Publication date that will be included
% on the title page.
%
% * `'figureScale='` [ numeric | *1* ] - Factor by which the graphics
% will be scaled.
%
% * `'irisVersion='` [ *`true`* | `false` ] - Display the current IRIS version
% in the header on the title page.
%
% * `'lineSpread='` [ numeric | *'auto'*] - Line spacing.
%
% * `'matlabVersion='` - Display the current Matlab version in the header on
% the title page.
%
% * `'numbered='` - [ *`true`* | `false` ] - Number sections.
%
% * `'package='` - [ cellstr | char | *'inconsolata'* ] - List of packages
% that will be loaded in the preamble.
%
% * `'paperSize='` -  [ 'a4paper' | *'letterpaper'* ] - Paper size.
%
% * `'preamble='` - [ char | *empty* ] - LaTeX commands
% that will be included in the preamble of the document.
%
% * `'template='` - [ *'paper'* | 'present' ] - Paper-like or
% presentation-like format.
%
% * `'textScale='` - [ numeric | *0.70* ] - Proportion of the paper used for
% the text body.
%
% * `'toc='` - [ *`true`* | `false` ] - Include the table of contents.
%
% Description
% ============
%
% Example
% ========
%

% -IRIS Toolbox.
% -Copyright (c) 2007-2012 Jaromir Benes.

opt = passvalopt('latex.publish',varargin{:});

if opt.toc && ~opt.numbered
    utils.error('latex', ...
        'Options ''numbered'' and ''toc'' are used inconsistently.');
end

if ischar(inputfile)
    inputfile = regexp(inputfile,'[^,;]+','match');
end
ninput = length(inputfile);

texfile = cell(1,ninput);
inputext = cell(size(inputfile));
inputtitle = cell(size(inputfile));
for i = 1 : ninput
    [inputpath,inputtitle{i},inputext{i}] = fileparts(inputfile{i});
    texfile{i} = [inputtitle{i},'.tex'];
    if i == 1 && (~exist('outputfile','var') || isempty(outputfile))
        outputfile = fullfile(inputpath,[inputtitle{i},'.pdf']);
    end
    if isempty(inputext{i})
        inputext{i} = '.m';
    end
end

% Old option name.
if ~isempty(opt.deletetempfiles)
    opt.cleanup = opt.deletetempfiles;
end

%**************************************************************************

br = sprintf('\n');

switch lower(opt.template)
    case 'paper'
        template = file2char(fullfile(irisroot(),'+latex','paper.tex'));
        if ~isnumericscalar(opt.linespread)
            opt.linespread = 1.1;
        end
    case 'present'
        template = file2char(fullfile(irisroot(),'+latex','present.tex'));
        if ~isnumericscalar(opt.linespread)
            opt.linespread = 1;
        end
        opt.toc = false;
    otherwise
        template = file2char(opt.template);
        if ~isnumericscalar(opt.linespread)
            opt.linespread = 1;
        end
end
template = strfun.converteols(template);

thisdir = pwd();
wdir = tempname(thisdir);
mkdir(wdir);

% Run input files with compact spacing.
spacing = get(0,'formatSpacing');
set(0,'formatSpacing','compact');

% Create mfile2xml (publish) options. The output directory is assumed to
% always coincide with the input file directory.
mfile2xmloptions = struct( ...
    'format','xml', ...
    'outputDir',wdir, ...
    ... 'imageDir',wdir, ...
    'imageFormat','epsc2', ...
    'evalCode',opt.evalcode, ...
    'useNewFigure',opt.usenewfigure);

% Try to copy all tex files to the working directory in case there are
% \input or \include commands.
try %#ok<TRYNC>
    copyfile('*.tex',wdir);
end

% Loop over all input files and produce XMLDOMs.
xmldoc = cell(1,ninput);
for i = 1 : ninput
    copy = xxpreparetopublish([inputtitle{i},inputext{i}]);
    % Only m-files can be published with `'evalCode='` true.
    if isequal(inputext{i},'.m')
        mfile2xmloptions.evalCode = opt.evalcode;
    else
        mfile2xmloptions.evalCode = false;
    end
    % Switch off warnings produced by the built-in publish when conversion
    % of latex equations to images fails.
    ss = warning();
    warning('off');%#ok<WNOFF>
    % Publish an xml file and read the file in again as xml object.
    xmlfile = publish([inputtitle{i},inputext{i}],mfile2xmloptions);
    warning(ss);
    xmldoc{i} = xmlread(xmlfile);
    char2file(copy,[inputtitle{i},inputext{i}]);
end

% Reset spacing.
set(0,'formatSpacing',spacing);

% Switch to the working directory so that `xml2tex` can find the graphics
% files.
cd(wdir);
try
    tex = cell(1,ninput);
    body = '';
    for i = 1 : ninput
        if ninput == 1
            type = 'single';
        elseif i == 1
            type = 'master';
        else
            type = 'multiple';
        end
        [tex{i},author] = latex.xml.xml2tex(xmldoc{i},type,opt);
        if isempty(opt.author) && i == 1 && ischar(author)
            opt.author = author;
        end
        tex{i} = xxdocsubs(tex{i},opt);
        char2file(tex{i},texfile{i});
        body = [body,'\input{',texfile{i},'}',br]; %#ok<AGROW>
    end
    
    template = strrep(template,'$body$',body);
    template = xxdocsubs(template,opt);
    
    char2file(template,'main.tex');
    latex.compilepdf('main.tex');
    copyfile('main.pdf',outputfile);
    movefile(outputfile,thisdir);
catch Error
    utils.warning('xml', ...
        'Error producing PDF. Matlab says: \n%s',Error.message);
end

cd(thisdir);
if opt.cleanup
    rmdir(wdir,'s');
end

if opt.closeall
    close('all');
end

end

% Subfunctions.

%**************************************************************************
function c = xxdocsubs(c,opt)
br = sprintf('\n');
c = strrep(c,'$papersize$',opt.papersize);
opt.author = strtrim(opt.author);
if ~isempty(opt.author)
    c = strrep(c,'$author$',['\byauthor ',opt.author]);
else
    c = strrep(c,'$author$','');
end
c = strrep(c,'$date$',opt.date);
c = strrep(c,'$textscale$',sprintf('%g',opt.textscale));
c = strrep(c,'$figurescale$',sprintf('%g',opt.figurescale));
if opt.matlabversion
    v = version();
    v = strrep(v,' ','');
    v = regexprep(v,'(.*)\s*\((.*?)\)','$2');
    c = strrep(c,'$matlabversion$', ...
        ['Matlab: ',v]);
else
    c = strrep(c,'$matlabversion$','');
end

if opt.irisversion
    c = strrep(c,'$irisversion$', ...
        ['IRIS: ',irisversion()]);
else
    c = strrep(c,'$irisversion$','');
end

% Packages.
if ~isempty(opt.package)
    c1 = '';
    if ischar(opt.package)
        opt.package = {opt.package};
    end
    npkg = length(opt.package);
    for i = 1 : npkg
        pkg = opt.package{i};
        if isempty(strfind(pkg,'{'))
            c1 = [c1,'\usepackage{',pkg,'}']; %#ok<AGROW>
        else
            c1 = [c1,'\usepackage',pkg]; %#ok<AGROW>
        end
        c1 = [c1,br]; %#ok<AGROW>
    end
    c = strrep(c,'$packages$',c1);
else
    c = strrep(c,'$packages$','');
end

c = strrep(c,'$preamble$',opt.preamble);
if opt.numbered
    c = strrep(c,'$numbered$','');
else
    c = strrep(c,'$numbered$','*');
end
linespread = sprintf('%g',opt.linespread);
c = strrep(c,'$linespread$',linespread);

end
% xxdocsubs().

%**************************************************************************
function copy = xxpreparetopublish(file)
% xxpreparetopublish  Remove formats not recognised by built-in publish.
c = file2char(file);
copy = c;
% Replace %... and %%% with %%% ...
c = regexprep(c,'^%[ \t]*\.\.\.\s*$','%% ...','lineanchors');
c = regexprep(c,'^%%%[ \t]*(?=\n)$','%% ...','lineanchors');
% Remove underlines % ==== with 4+ equal signs.
c = regexprep(c,'^% ?====+','%','lineanchors');
% Remove underlines % ---- with 4+ equal signs.
c = regexprep(c,'^% ?----+','%','lineanchors');
% Replace ` with |.
c = strrep(c,'`','|');
char2file(c,file);
end
% preparetopublish().