% This file creates tikz plot files

% O has fields:
%  - plot_name (=file name)
%  - data (Cell, will be saved in path_tikz/csv). Each cell has 2 col vectors if regular line plot, for bar plot each cell has 1 col vector representing a category 
%  - colors (string such as "blue!20!red")
%  - yaxis{ }
%  - xaxis{ }
%  - title
%  - legend{ }



% OPTIONAL:
%  - xtick = { } 
%  - ytick = { }
%  - axis  = 'axis' (default), 'semilogyaxis', 'loglogaxis' 
%  - xlabel (eg ."time $t$")
%  - scale (what scale does it have?)
%  - fliplegend (0,1: reverse order of legend)
%  - ylabel
%  - width (e.g. "3in")
%  - height (e.g. "2in")
%  - width_off , if = 1, then it uses preset width style "wstyle" which
%     must be set in the lyx file using \pgfplotsset{wstyle/.style = {width
%     = 4in}}
%  - height_off, if = 1, same as width off
%  - xaxis_pos (e.g. "bottom" ) if not included: box
%  - yaxis_pos (e.g."bottom") if not included: box
%  - xaxis_percent = 0,1 switches percent on
%  - yaxis_percent = 0,1 switches percent on. if = 'bla' then bla will be
%                       shown instead of a unit or percent sign
%  - yscalelabel (e.g. "of GDP") appears on top of axis
%  - yscalelabelpos (e.g. "at={(1,0)},yshift=5pt,anchor=south") governs
%    position of yscalelabel
%  - styles (e.g. {'dashed', 'loosely dashed', 'densely dashed', 'dotted'...}
%  - legend_cols: -1,1,2, how many legend cols there can be (-1 = inf)
%  - globalstyle: styles applied to ALL lines!
%  - errorbars: = 0 1: show error bars. Note if = 1, add to globalstyle: (e.g.)
%         error bars/.cd, %
% 		x dir = both, %
% 		y dir = both, y explicit,%
% 		error mark=none, %
% 		error bar style = {black!40}
%
%  - barplot (e.g. 0, 1) : produce upright stacked bar plot. NOTE: Each col in the data file is a category (color) in the plot 
%  - enlargex (e.g. 0.625) : how large x is or so?
%  - barwidth (e.g. 10mm) : width of a bar
%  - barlabels (e.g. {a,b}) : labels below bars
%  - secondyaxis (only for a single line): struct with the following fields: 
%         - range: row vec with indices in data that should have the second y axis 
%         - yaxis
%         - ylabel (optional)
%         - ytick (optional)
%         - yaxis_percent (optional)
%         
% - compile_pdf:  (0,1) compile pdfs
% - compile_pdf_folder: folder to move the compiled pdf into (required)
% - paperpath
% - pdflatex folder
% - compile_pdf_tikzfolder: tikz subfolder of paper path
% - addstyle : (0,1) add "addstyle" to options of axis. This allows using
%     \pgfplotsset{addstyle/.style={ ... }} to add additional options outside the tikz file 
% - addstyle_tikz: same for tikz with \tikzset{addstyle/.style={...}}


function error = write_tikz_file(O, path_tikz)

%%% load a few inputs
if isfield(O,'styles') ~= 1
    styles = cell(1,numel(O.colors));
    [styles{:}] = deal('');
else
    styles = O.styles;
end

if numel(styles) ~= numel(O.colors)
    warning 'Can only accept as many styles as there are colors !'
end
barplot = read_opt(O,'barplot',0);
scale = read_opt(O,'scale',0.8);
xtick = read_opt(O,'xtick',{0});
ytick = read_opt(O,'ytick',{0});
legend_cols = read_opt(O,'legend_cols',-1); % how many legend columns there can be. -1 = infinitely many
globalstyle = read_opt(O,'globalstyle','line width = 1pt,mark=none');
errorbars   = read_opt(O,'errorbars',[]);
secondyaxis = read_opt(O,'secondyaxis',struct);
if isfield(secondyaxis,'range') ~= 1
    secondyaxis.range = [];
end
scaleonlyaxis  = read_opt(O,'scaleonlyaxis',0);
addstyle       = read_opt(O,'addstyle',0);
addstyle_tikz  = read_opt(O,'addstyle_tikz',0);
yscalelabel    = read_opt(O,'yscalelabel','');
yscalelabelpos = read_opt(O,'yscalelabelpos','at={(0,1)},anchor=south,yshift=4pt');




%%% copy the right template
if barplot == 0
    template = [path_tikz '_template_.tikz'];
elseif barplot == 1
    template = [path_tikz '_barplot_template_.tikz'];
end
newfile  = [path_tikz O.plot_name '.tikz'];
copyfile(template, newfile);


%%% save csv file
% first figure out max length of the data
N = numel(O.data);
max_length = 0;
for n = 1:N
    data = O.data{n};
    max_length = max(max_length,numel(data(:,1)));
end

% now bring it all to the same length by filling up with nan's
DATA = [];
for n = 1:N
    data   = O.data{n};
    length = numel(data(:,1));
    width  = numel(data(1,:));
    if length < max_length
        data = [data; NaN * ones(max_length-length,width)];
    end
    if width < 3 && isempty(errorbars) && barplot == 0% add zeros (error column)
        data = [data zeros(max_length,3-width)];
    end
    DATA = [DATA data];
end

% save data
csvwrite([path_tikz 'csv/' O.plot_name '.csv'],DATA);
csvwrite([path_tikz 'tikz/csv/' O.plot_name '.csv'],DATA); % also save here to be able to compile the file!


%%% find and replace a bunch of stuff in the new file
n = 1;

% scale
placeholder{n} = '_SCALE_';
replaceby{n}   = num2str(scale);
if addstyle_tikz == 1
    replaceby{n} = [replaceby{n} ', addstyle'];
end
n = n+1;

% color list
placeholder{n} = '_COLORLIST_';
string = '';
for m = 1:numel(O.colors)
    % beginning
    string = [string '{'];
    
    % add "fill = " if barplot
    if barplot
        string = [string 'fill='];
    end
    
    % write color
    string = [ string O.colors{m}];
    
    % write style
    if strcmp(styles{m},'') == false
        string = [string ',' styles{m}];
    end
    
    % ending
    if m == numel(O.colors)
        string = [string '}%'];
    else
        string = [string '},'];
    end
%     string = [string ' %\n'];
end
% string = [string '}'];
replaceby{n}   = string; n = n+1;

% csv file
placeholder{n} = '_CSVFILENAME_';
replaceby{n}   = ['tikz/csv/' O.plot_name '.csv']; n = n+1;

% axes
placeholder{n} = '_YMIN_';
replaceby{n}   = num2str(O.yaxis{1}); n = n+1;
placeholder{n} = '_YMAX_';
replaceby{n}   = num2str(O.yaxis{2}); n = n+1;
placeholder{n} = '_XMIN_';
replaceby{n}   = num2str(O.xaxis{1}); n = n+1;
placeholder{n} = '_XMAX_';
replaceby{n}   = num2str(O.xaxis{2}); n = n+1;

% legend
placeholder{n} = '_LEGEND_';
replaceby{n}   = [O.plot_name '_legend']; n = n+1;

% x ticks
placeholder{n} = '_XTICKS_';
string = '{';
for m = 1:numel(xtick)
    if m == 1
        string = [ string num2str(xtick{m})];
    else
        string = [string ',' num2str(xtick{m})];
    end
end
string = [string '}'];
replaceby{n}   = string; n = n+1;

% y ticks
placeholder{n} = '_YTICKS_';
string = '{';
for m = 1:numel(ytick)
    if m == 1
        string = [ string num2str(ytick{m})];
    else
        string = [string ',' num2str(ytick{m})];
    end
end
string = [string '}'];
replaceby{n}   = string; n = n+1;

% title
placeholder{n} = '_TITLE_';
replaceby{n}   = O.title; n = n+1;

% legend
for m = 1:numel(O.legend)
    string = ['[black] ' O.legend{m} ' $\\quad$'];
    if m < numel(O.legend)
        string = [string ',%'];
    else
        string = [string '%'];
    end
    placeholder{n} = ['%_LEGEND' num2str(m) '_'];
    replaceby{n}   = string; n=n+1;
end

% no lines
N_lines = N - barplot - numel(secondyaxis.range); % barplot: N-1 !
line_range = [1:N]; line_range(secondyaxis.range) = [];
placeholder{n} = '_LINECOUNTER_';
string = '{';
for m = 1:N_lines
    index = line_range(m);
    if m == 1
        string = [ string num2str(index)];
    else
        string = [string ',' num2str(index)];
    end
end
string = [string '}'];
replaceby{n}   = string; n = n+1;

% x label
if isfield(O,'xlabel') ~= 0
    placeholder{n} = '_XLABEL_';
    replaceby{n}   = O.xlabel; n = n+1;
else % default value
    placeholder{n} = '_XLABEL_';
    replaceby{n}   = 'time $t$ (years)'; n = n+1;
end

% y label
if isfield(O,'ylabel') ~= 0
    placeholder{n} = '_YLABEL_';
    replaceby{n}   = O.ylabel; n = n+1;
else % default value
    placeholder{n} = '_YLABEL_';
    replaceby{n}   = ''; n = n+1;
end

% width
placeholder{n} = '_WIDTH_';
width     = read_opt(O,'width','3in');
width_off = read_opt(O,'width_off',0);
if width_off == 0
    replaceby{n}   = ['width = ' width ' ,']; n = n+1;
else
    replaceby{n}   = 'wstyle,'; n = n+1;
end

% height
placeholder{n} = '_HEIGHT_';
height     = read_opt(O,'height','2in');
height_off = read_opt(O,'height_off',0);
if height_off == 0
    replaceby{n}   = ['height = ' height ' ,']; n = n+1;
else
    replaceby{n}   = 'hstyle,'; n = n+1;
end

% xaxis_pos
if isfield(O,'xaxis_pos') ~= 0
    placeholder{n} = '_XAXIS_POS_';
    noarrow = read_opt(O,'xaxis_pos_noarrow',0);
    if noarrow == 0
        replaceby{n}   = ['axis x line = ' O.xaxis_pos ', ']; n = n+1;
    else
        replaceby{n}   = ['axis x line* = ' O.xaxis_pos ', ']; n = n+1;
    end
else % default value
    placeholder{n} = '_XAXIS_POS_';
    replaceby{n}   = ''; n = n+1;
end

% yaxis_pos
if isfield(O,'yaxis_pos') ~= 0
    placeholder{n} = '_YAXIS_POS_';
    noarrow = read_opt(O,'yaxis_pos_noarrow',0);
    if noarrow == 0
        replaceby{n}   = ['axis y line = ' O.yaxis_pos ', ']; n = n+1;
    else
        replaceby{n}   = ['axis y line* = ' O.yaxis_pos ', ']; n = n+1;
    end
else % default value
    placeholder{n} = '_YAXIS_POS_';
    replaceby{n}   = ''; n = n+1;
end


% log axis?
axis = read_opt(O,'axis','axis');
placeholder{n} = '_AXIS_';
replaceby{n}   = axis;  n = n+1;

% yaxis_percent (note: log axis requires adjustment for percent)
O.yaxis_percent = read_opt(O,'yaxis_percent',0);
if O.yaxis_percent ~= 0
    placeholder{n} = '_YAXIS_PERCENT_';
    if strcmp(axis,'semilogyaxis') || strcmp(axis,'loglogaxis')
        firstpart = 'yticklabel=\\pgfmathparse{exp(\\tick)}';
    else
        firstpart = 'yticklabel=\\pgfmathparse{\\tick}';
    end
    if ischar(O.yaxis_percent)
        % use specific suffix
        replaceby{n}   = [firstpart '\\pgfmathprintnumber{\\pgfmathresult}\\(\\,' O.yaxis_percent '\\), ']; n = n+1;
    else
        replaceby{n}   = [firstpart '\\pgfmathprintnumber{\\pgfmathresult}\\(\\,\\%\\), ']; n = n+1;
    end
else % default value
    placeholder{n} = '_YAXIS_PERCENT_';
    replaceby{n}   = ''; n = n+1;
end

% xaxis_percent
O.xaxis_percent = read_opt(O,'xaxis_percent',0);
if O.xaxis_percent ~= 0
    placeholder{n} = '_XAXIS_PERCENT_';
    if strcmp(axis,'semilogxaxis') || strcmp(axis,'loglogaxis')
        firstpart = 'log ticks with fixed point, xticklabel=\\pgfmathparse{exp(\\tick)}';
    else
        firstpart = 'xticklabel=\\pgfmathparse{\\tick}';
    end
    if ischar(O.xaxis_percent)
        % use specific suffix
        replaceby{n}   = [firstpart '\\pgfmathprintnumber{\\pgfmathresult}\\(' O.xaxis_percent '\\), ']; n = n+1;
    else
        replaceby{n}   = [firstpart '\\pgfmathprintnumber{\\pgfmathresult}\\(\\,\\%\\), ']; n = n+1;
    end
else % default value
    placeholder{n} = '_XAXIS_PERCENT_';
    if strcmp(axis,'semilogxaxis') || strcmp(axis,'loglogaxis')
        replaceby{n}   = 'log ticks with fixed point,'; n = n+1;
    else
        replaceby{n}   = ''; n = n+1;
    end
end

% yscalelabel
placeholder{n} = '_YSCALELABEL_';
if strcmp(yscalelabel,'')
    replaceby{n}   = '%';  n = n+1;
else
    replaceby{n}   = ['scaled y ticks=manual:{' yscalelabel '}{\pgfmathparse{#1}}'];  n = n+1;
end

% yscalelabelpos
placeholder{n} = '_YSCALELABELPOS_';
replaceby{n}   = ['every y tick scale label/.style={' yscalelabelpos '}'];  n = n+1;

% legend_cols
placeholder{n} = '_LEGENDCOLS_';
replaceby{n}   = num2str(legend_cols);  n = n+1;

% globalstyle
placeholder{n} = '_GLOBALSTYLE_';
replaceby{n}   = globalstyle;  n = n+1;

% errorbars
placeholder{n} = '_ERROR_';
if errorbars == 1
    replaceby{n}   = ', y error index = \\eindex';  n = n+1;
else
    replaceby{n}   = ''; n = n+1;
end



% second y axis?
placeholder{n} = '%_SECONDYAXIS_';
if isempty(secondyaxis.range) ~= 1
    O2 = secondyaxis;
    
    % activate
    placeholder{n} = '\\iffalse %Y2';
    replaceby{n}   = '%'; n = n+1;
    placeholder{n} = '\\fi %Y2';
    replaceby{n}   = '%'; n = n+1;
    
    % yaxis_percent
    if isfield(O2,'yaxis_percent') ~= 0 || isfield(O,'yaxis_percent') ~= 0
        placeholder{n} = '_YAXIS2_PERCENT_';
        O2.yaxis_percent = read_opt(O2,'yaxis_percent',O.yaxis_percent);
        if ischar(O2.yaxis_percent)
            % use specific suffix
            replaceby{n}   = ['yticklabel=\\pgfmathparse{\\tick}\\pgfmathprintnumber{\\pgfmathresult}\\(\\,' O2.yaxis_percent '\\), ']; n = n+1;
        else
            replaceby{n}   = ['yticklabel=\\pgfmathparse{\\tick}\\pgfmathprintnumber{\\pgfmathresult}\\(\\,\\%\\), ']; n = n+1;
        end
    else % default value
        placeholder{n} = '_YAXIS2_PERCENT_';
        replaceby{n}   = ''; n = n+1;
    end
    
    % y label
    if isfield(O2,'ylabel') ~= 0
        placeholder{n} = '_YLABEL2_';
        replaceby{n}   = O.ylabel; n = n+1;
    else % default value
        placeholder{n} = '_YLABEL2_';
        replaceby{n}   = '{}'; n = n+1;
    end
    
    % LINE counter
    line_range = secondyaxis.range; N_lines = numel(line_range);
    placeholder{n} = '_LINECOUNTER2_';
    string = '{';
    for m = 1:N_lines
        index = line_range(m);
        if m == 1
            string = [ string num2str(index)];
        else
            string = [string ',' num2str(index)];
        end
    end
    string = [string '}'];
    replaceby{n}   = string; n = n+1;
    
    % scale only
    placeholder{n} = '_SCALEONLY2_';
    if scaleonlyaxis == 1
        replaceby{n}   = 'scale only axis,'; n = n+1;
    else
        replaceby{n}   = ''; n = n+1;
    end
    
    % ensure correct legend
    placeholder{n} = '_LINECOUNTERLEGEND_';
    replaceby{n}   = string; n = n+1;
    
    % y ticks
    placeholder{n} = '_YTICKS2_';
    if isfield(O2,'ytick')
        string = 'ytick = {';
        for m = 1:numel(O2.ytick)
            if m == 1
                string = [ string num2str(O2.ytick{m})];
            else
                string = [string ',' num2str(O2.ytick{m})];
            end
        end
        string = [string '},'];
    else
        string = '';
    end
    replaceby{n}   = string; n = n+1;

    placeholder{n} = '_YMIN2_';
    replaceby{n}   = num2str(O2.yaxis{1}); n = n+1;
    placeholder{n} = '_YMAX2_';
    replaceby{n}   = num2str(O2.yaxis{2}); n = n+1;
    
    % set first axis options right
    placeholder{n} = '_Y2EXTRAS_';
    if scaleonlyaxis == 1
        replaceby{n}   = 'scale only axis, axis y line* = left,'; n = n+1;
    else
        replaceby{n}   = 'axis y line* = left,'; n = n+1;
    end
    
    % color list
    placeholder{n} = '_COLORLIST2_';
    O2.colors = O.colors(secondyaxis.range);
    O2.styles = styles(secondyaxis.range);
    string = '';
    for m = 1:numel(O2.colors)
        % beginning
        string = [string '{'];

        % add "fill = " if barplot
        if barplot
            string = [string 'fill='];
        end

        % write color
        string = [ string O2.colors{m}];

        % write style
        if strcmp(O2.styles{m},'') == false
            string = [string ',' O2.styles{m}];
        end

        % ending
        if m == numel(O2.colors)
            string = [string '}%'];
        else
            string = [string '},'];
        end
    %     string = [string ' %\n'];
    end
    
    replaceby{n}   = string; n = n+1;
    
    % color the axis?
    coloraxis = read_opt(secondyaxis,'coloraxis',0);
    placeholder{n} = '_COLORY2_';
    if coloraxis == 1
        replaceby{n}   = ['y axis style = ' O2.colors{1} ',']; n = n+1;
    else
        replaceby{n}   = '';n = n+1;
    end
    
else
    % eliminate stuff
    placeholder{n} = '_Y2EXTRAS_';
    replaceby{n}   = ''; n = n+1;
    placeholder{n} = '_LINECOUNTERLEGEND_';
    replaceby{n}   = '{}'; n = n+1;
end



%%% EXTRAS:
% flip order of legend
placeholder{n} = '_EXTRAS_';
replaceby{n}   = '';
if isfield(O,'flip_legend') ~= 0
    if O.flip_legend == 1
        replaceby{n}   = [replaceby{n} ', reverse legend'];
    end
end
if addstyle == 1
    replaceby{n}   = [replaceby{n} ', addstyle'];
end
n = n+1;

if barplot == 1
    % extra bar plot options
    enlargex = read_opt(O,'enlargex',0.625);
    barwidth = read_opt(O,'bardwith','10mm');
    barlabels = read_opt(O,'barlabels',{'A'});
    
    % enlargex
    placeholder{n} = '_ENLARGEX_';
    replaceby{n}   = num2str(enlargex); n = n+1;
    
    % barwidth
    placeholder{n} = '_BARWIDTH_';
    replaceby{n}   = barwidth; n = n+1;
    
    % Bar labels
    placeholder{n} = '_XTICKLABELS_';
    string = '{';
    for m = 1:numel(barlabels)
        if m == 1
            string = [ string num2str(barlabels{m})];
        else
            string = [string ',' num2str(barlabels{m})];
        end
    end
    string = [string '}'];
    replaceby{n}   = string; n = n+1;
end


%%% replace these things in the new file
for i = 1:numel(placeholder)
    find_and_replace(newfile,placeholder{i},replaceby{i});
end


%%% Compile pdfs
compile_pdf = read_opt(O,'compile_pdf',0);
if compile_pdf == 1
    
    pdf_folder    = read_opt(O,'compile_pdf_folder','');
    tikz_folder   = read_opt(O,'compile_pdf_tikzfolder','tikz/');
    paperpath     = O.compile_pdf_paperpath;
    pdflatexpath  = read_opt(O,'pdflatexpath','/usr/local/texlive/2018/bin/x86_64-darwin');
    
    % compile the tikz file
    PATH = getenv('PATH');
    setenv('PATH', [PATH ':' pdflatexpath]);
    
    command1 = ['cd "' paperpath '"'];
    command2 = ['python tikz2pdf.py ' tikz_folder O.plot_name '.tikz' ];
    
    unix([command1 ' && ' command2]);
    
    % move file
    movefile([paperpath tikz_folder O.plot_name '.pdf'], [paperpath pdf_folder]);
end

display(['Successfully wrote: ' newfile])

error = 0;

end
