function [c,author] = xml2tex(x,type,options)
% xml2tex  Convert publish XML to TEX code.
%
% Backend IRIS function.
% No help provided.

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

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

% First input can be either a xml dom or a xml file name.
if ischar(x)
    x = xmlread(x);
end

xxoriginalcode(x);
xxbookmarks();

% Overview cell (introduction).
[c,author] = xxintroduction(x,type,options);

% Table of contents.
c = [c,xxtoc(x,type,options)];

if isequal(type,'master')
    return
end

% Normal cells.
y = latex.xml.xpath(x,'//cell[not(@style="overview")]','nodeset');
n = y.getLength();
for i = 1 : n
    c = [c,xxnormalcell(y.item(i-1),type,options)];
end

% Fix idiosyncrasies.
c = xxidiosyncrasy(c);

end

% Subfunctions.

%**************************************************************************
function c = xxbookmarks(b)
persistent bookmarks typeset;
if nargin == 0 && nargout == 0
    code = xxoriginalcode();
    bookmarks = regexp(code,'%\?(\w+)\?','tokens');
    bookmarks = [bookmarks{:}];
    [~,index] = unique(bookmarks,'first');
    bookmarks = bookmarks(sort(index));
    nbkm = length(bookmarks);
    typeset = xxbookmarktypeset();
    typeset = typeset(1:nbkm);
    return
end
c = '';
if ischar(b)
    index = strcmp(b,bookmarks);
    if any(index)
        c = typeset{index};
    else
        c = '?';
    end
    c = ['\bookmark{',c,'}'];
end
end
% xxbookmarks().

%**************************************************************************
function [c,author] = xxintroduction(x,type,options)
c = '';
br = sprintf('\n');
[ans,ftit,fext] = ...
    fileparts(latex.xml.xpath(x,'//filename','string')); %#ok<NOANS,ASGLU>
mfilename = [ftit,fext];
[~,~,fext] = fileparts(mfilename);
if isempty(fext)
    mfilename = [mfilename,'.m'];
end
% Read title.
title = latex.xml.xpath(x,'//cell[@style="overview"]/steptitle','node');
title = xxtext(title);
title = strtrim(title);
emptytitle = isempty(title);
% Read first paragraph and check if it gives the authors.
author = NaN;
p = latex.xml.xpath(x, ...
    '//cell[@style="overview"]/text/p[position()=1]','node');
if ~isempty(p)
    temp = strtrim(char(p.getTextContent()));
    if strncmp(temp,'by ',3)
        author = strrep(temp(4:end),'&', ' \and ');
        % Remove the first paragraph.
        p.getParentNode.removeChild(p);
    end
end
% Read abstract.
abstract = latex.xml.xpath(x,'//cell[@style="overview"]/text','node');
abstract = xxtext(abstract);
abstract = strtrim(abstract);
% Read file name.
mfilename = xxspecchar(mfilename);
switch type
    case 'single'
        if ~emptytitle
            c = [c, ...
                '\introduction{',title,'}', ...
                '{\mfilenametitle{',mfilename,'}}',br, ...
                ];
        else
            c = [c,'\introduction{',mfilename,'}{}',br];
        end
        if ~isempty(abstract)
            c = [c,'\begin{myabstract}',abstract,'\end{myabstract}',br];
        end
    case 'master'
        if ~emptytitle
            c = [c,'\introduction{',title,'}','{}',br];
        else
            c = [c,'\introduction{',mfilename,'}{}',br];
        end
        if ~isempty(abstract)
            c = [c,'\begin{abstract}',abstract,'\end{abstract}',br];
        end
    case 'multiple'
        c = ['\clearpage',br];
        if emptytitle
            tocentry = title;
        else
            tocentry = [title,' --- \texttt{',mfilename,'}'];
        end
        if options.numbered
            c = [c,'\section[',tocentry,']{',title];
        else
            c = [c,'\section*{',title];
        end
        if ~emptytitle
            c = [c,' \mfilenametitle{',mfilename,'}'];
        end
        c = [c,'}',br];
end
if ~isequal(type,'master')
    c = [c, ...
        '\renewcommand{\filetitle}{',title,'}',br, ...
        '\renewcommand{\mfilename}{',mfilename,'}',br];
    c = [c,br,'\bigskip\par'];
end
c = [c,br,br];
end
% xxintroduction().

%**************************************************************************
function c = xxtoc(x,type,options) %#ok<INUSL>
br = sprintf('\n');
c = '';
if ~options.toc || isequal(type,'multiple')
    return
end
if isequal(type,'master')
    c = [c,'\clearpage',br];
end
c = [c,'\mytableofcontents',br,br];
end
% toc().

%**************************************************************************
function c = xxnormalcell(x,type,options) %#ok<INUSD>
br = sprintf('\n');
title = strtrim(latex.xml.xpath(x,'steptitle','string'));
if isequal(title,'...')
    cbegin = '\begin{splitcell}';
    cend = '\end{splitcell}';
else
    cbegin = ['\begin{cell}{',title,'}'];
    cend = '\end{cell}';
end
c = '';
% Intro text.
c1 = xxtext(latex.xml.xpath(x,'text','node'));
if ~isempty(c1)
    c = [c,'\begin{introtext}',br];
    c = [c,c1,br];
    c = [c,'\end{introtext}',br];
end
% Input code.
y = latex.xml.xpath(x,'mcode','node');
if ~isempty(y)
    inputcode = char(y.getTextContent());
    inputcode = strfun.converteols(inputcode);
    inputcode = strfun.removetrails(inputcode);
    [~,n] = xxoriginalcode(inputcode);
    replace = @xxbookmarks; %#ok<NASGU>
    inputcode = regexprep(inputcode,'%\?(\w+)\?','"${replace($1)}"');
    c = [c,br, ...
        '\begin{inputcode}',br, ...
        '\lstset{firstnumber=',sprintf('%g',n),'}',br, ...
        '\begin{lstlisting}',br, ...
        inputcode, ...
        '\end{lstlisting}',br, ...
        '\end{inputcode}'];
end
% Output code.
outputcode = latex.xml.xpath(x,'mcodeoutput','node');
if ~isempty(outputcode)
    outputcode = char(outputcode.getTextContent());
    outputcode = strfun.converteols(outputcode);
    c = [c,br, ...
        '\begin{outputcode}',br, ...
        '\begin{lstlisting}',br, ...
        outputcode, ...
        '\end{lstlisting}',br, ...
        '\end{outputcode}',br];
end
% Images that are part of code output.
images = latex.xml.xpath(x,'img','nodeset');
nImg = images.getLength();
if nImg > 0
    for iImg = 1 : nImg
        c = [c,xximg(images.item(iImg-1))];
    end
end
c = [cbegin,br,c,br,cend,br,br];
end
% xxnormalcell().

%**************************************************************************
function [code1,n] = xxoriginalcode(x)
persistent code;
if exist('x','var') && ~ischar(x)
    % Initialise `originalcode` when `x` is an xml dom.
    code = latex.xml.xpath(x,'//originalCode','string');
    code = strfun.converteols(code);
    code = strfun.removetrails(code);
end
code1 = code;
if nargout < 2
    return
end
ncode = length(x);
start = strfind(code,x);
if isempty(start)
    disp(x);
    utils.error('latex', ...
        'The above m-file code segment not found.');
end
start = start(1);
finish = start + ncode - 1;
n = sum(code(1:start-1) == char(10)) + 1;
nreplace = sum(x == char(10));
replace = char(10*ones(1,nreplace));
code = [code(1:start-1),replace,code(finish+1:end)];
end
% originalcode().

%**************************************************************************
function c = xxtext(x)
c = '';
if isempty(x)
    return
end
br = sprintf('\n');
x = latex.xml.xpath(x,'node()','nodeset');
n = x.getLength();
for i = 1 : n
    this = x.item(i-1);
    switch char(this.getNodeName)
        case 'latex'
            c1 = char(this.getTextContent());
            c1 = strrep(c1,'<latex>','');
            c1 = strrep(c1,'</latex>','');
            c = [c,br,br,c1,br]; %#ok<*AGROW>
        case 'p'
            % Paragraph.
            c = [c,br,'\begin{par}',xxtext(this), ...
                '\end{par}'];
        case 'a'
            % Bookmark in the text.
            c1 = char(this.getTextContent());
            if ~isempty(c1) && all(c1([1,end]) == '?')
                c1 = xxbookmarks(c1(2:end-1));
            else
                c1 = xxtext(this);
                c1 = ['\texttt{\underline{',c1,'}}'];
            end
            c = [c,c1];
        case 'b'
            c = [c,'\textbf{',xxtext(this),'}'];
        case 'i'
            c = [c,'\textit{',xxtext(this),'}'];
        case 'tt'
            c = [c,'{\codesize\texttt{',xxtext(this),'}}'];
        case 'ul'
            c = [c,'\begin{itemize}',xxtext(this), ...
                '\end{itemize}'];
        case 'ol'
            c = [c,'\begin{enumerate}',xxtext(this), ...
                '\end{enumerate}'];
        case 'li'
            c1 = strtrim(xxtext(this));
            n = length('\bookmark{');
            if strncmp(c1,'\bookmark{',n)
                % Item starting with a bookmark.
                close = strfun.matchbrk(c1,n);
                if isempty(close)
                    close = 0;
                end
                c = [c,'\item[',c1(1:close),'] ',c1(close+1:end)];
            else
                % Regular item.
                c = [c,'\item ',c1];
            end
        case 'pre'
            % If this is a <pre class="error">, do not display
            % anything.
            if ~strcmp(char(this.getAttribute('class')),'error')
                c1 = char(this.getTextContent());
                c = [c,'{\codesize\begin{verbatim}',c1, ...
                    '\end{verbatim}}'];
            end
        case 'img'
            % This is an equation converted successfully to an image.
            % Retrieve the original latex code from the attribute alt.
            % We do not need to capture the name of the source image
            % because it is inside the temp directory, and will be
            % deleted at the end.
            if strcmp(char(this.getAttribute('class')),'equation')
                alt = char(this.getAttribute('alt'));
                c = [c,alt]; %#ok<AGROW>
            end
        case 'equation'
            % An equation element either contains a latex code directly
            % (if conversion to image failed), or an image element.
            c1 = char(this.getTextContent());
            c1 = strtrim(c1);
            if isempty(c1)
                % Image element.
                c1 = xxtext(this);
                c1 = strtrim(c1);
            end
            c = [c,c1]; %#ok<AGROW>
        otherwise
            c1 = char(this.getTextContent());
            c1 = regexprep(c1,'\s+',' ');
            c1 = xxspecchar(c1);
            c = [c,c1]; %#ok<AGROW>
    end
end
end
% text().

%**************************************************************************
function c = xxidiosyncrasy(c)
c = strrep(c,'\end{itemize}\begin{itemize}','');
c = strrep(c,'\end{enumerate}\begin{enumerate}','');
end
% idiosyncrasy().

%**************************************************************************
function c = xximg(x)
% File name in the `src` attribute is a relative path wrt the original
% directory. We only need to refer to the file name.
fname = latex.xml.xpath(x,'@src','string');
[~,ftitle,fext] = fileparts(fname);
c = '';
if ~exist([ftitle,fext],'file')
    utils.warning('xml', ...
        'Image file not found: ''%s''.',[ftitle,fext]);
    return
end
if isequal(fext,'.eps')
    latex.epstopdf([ftitle,fext]);
    fext = '.pdf';
end
br = sprintf('\n');
c = [br,'{\centering', ...
    br,'\includegraphics[scale=$figurescale$]{',[ftitle,fext],'}', ...
    br,'\par}'];
end
% img().

%**************************************************************************
function c = xxspecchar(c)
c = strrep(c,'\','\textbackslash ');
c = strrep(c,'_','\_');
c = strrep(c,'%','\%');
c = strrep(c,'$','\$');
c = strrep(c,'#','\#');
c = strrep(c,'&','\&');
c = strrep(c,'<','\ensuremath{<}');
c = strrep(c,'>','\ensuremath{>}');
c = strrep(c,'~','\ensuremath{\sim}');
c = strrep(c,'^','\^{ }');
end
%specchar().

%**************************************************************************
function x = xxbookmarktypeset()
x = {
    '1'
    '2'
    '3'
    '4'
    '5'
    '6'
    '7'
    '8'
    '9'
    'a'
    'b'
    'c'
    'd'
    'e'
    'f'
    'g'
    'h'
    'i'
    'j'
    'k'
    'l'
    'm'
    'n'
    'o'
    'p'
    'q'
    'r'
    's'
    't'
    'u'
    'v'
    'w'
    'x'
    'y'
    'z'
    'A'
    'B'
    'C'
    'D'
    'E'
    'F'
    'G'
    'H'
    'I'
    'J'
    'K'
    'L'
    'M'
    'N'
    'O'
    'P'
    'Q'
    'R'
    'S'
    'T'
    'U'
    'V'
    'W'
    'X'
    'Y'
    'Z'
    '$\alpha$'
    '$\beta$'
    '$\gamma$'
    '$\delta$'
    '$\epsilon$'
    '$\zeta$'
    '$\eta$'
    '$\theta$'
    '$\iota$'
    '$\kappa$'
    '$\lambda$'
    '$\mu$'
    '$\nu$'
    '$\xi$'
    '$\pi$'
    '$\varrho$'
    '$\sigma$'
    '$\tau$'
    '$\upsilon$'
    '$\phi$'
    '$\chi$'
    '$\psi$'
    '$\omega$'
    '$\Gamma$'
    '$\Delta$'
    '$\Theta$'
    '$\Lambda$'
    '$\Xi$'
    '$\Pi$'
    '$\Sigma$'
    '$\Upsilon$'
    '$\Phi$'
    '$\Psi$'
    '$\Omega$'
    };
end
% bookmarktypeset().