classdef tabularobj < report.genericobj
    
    properties
        ncol = NaN;
        nlead = NaN;
        nrow = NaN;
        vline = [];
    end
    
    methods
        
        function THIS = tabularobj(varargin)
            THIS = THIS@report.genericobj(varargin{:});
            THIS.default = [THIS.default, { ...
                'arraystretch',1.15,@(x) isnumericscalar(x) && x > 0,true, ...
                'colspec','',@ischar,true, ...                
                'colwidth',NaN,@isnumeric,true, ...
                'long',false,@islogicalscalar,true, ...
                'longfoot','',@ischar,true, ...
                'longfootposition','l', ...
                    @(x) ischar(x) && any(strncmpi(x,{'l','c','r'},1)),true, ...
                'sideways',false,@islogicalscalar,true, ...
                'tabcolsep',NaN,@(x) isnumericscalar(x) && (isnan(x) || x >= 0), true, ...
            }];
        end
        
        function [THIS,varargin] = setoptions(THIS,varargin)
            THIS = setoptions@report.genericobj(THIS,varargin{:});
        end
        
        function C = begin(THIS)
            br = sprintf('\n');
            C = '';
            C = [C,beginsideways(THIS)];
            if ~THIS.options.long
                space = 7;
            else
                space = 0;
            end
            % Set arraystretch and tabcolsep.
            params = [ ...
                br,'\renewcommand{\arraystretch}{', ...
                sprintf('%g',THIS.options.arraystretch),'}', ...
                ];
            if ~isnan(THIS.options.tabcolsep)
                params = [params, ...
                br,'\settowidth\tabcolsep{m}', ...
                '\setlength\tabcolsep{', ...
                sprintf('%g',THIS.options.tabcolsep), ...
                '\tabcolsep}'];
            end
            % Wrap the content using another tabular to keep the
            % title/subtitle on the same page.
            C = [C,beginwrapper(THIS,space)];
            if ~THIS.options.long
                C = [C,'{',params,br,'\begin{tabular}'];
            else
                C = [C,finishwrapper(THIS)];
                C = [C,'\vspace*{-3pt}'];
                C = [C,'{',params,br,'\begin{longtable}'];
            end
            if THIS.options.colspec(1) ~= '{'
                THIS.options.colspec = ['{',THIS.options.colspec];
            end
            if THIS.options.colspec(end) ~= '}'
                THIS.options.colspec = [THIS.options.colspec,'}'];
            end
            C = [C,THIS.options.colspec];
            if THIS.options.long && ~isempty(THIS.options.longfoot)
                C = [C,br, ...
                    '\\[-10pt] \multicolumn', ...
                    '{',sprintf('%g',THIS.nlead+THIS.ncol),'}', ...
                    '{',THIS.options.longfootposition(1),'}', ...
                    '{',latex.stringsubs(THIS.options.longfoot),'}', ...
                    br,'\endfoot\endlastfoot'];
            end
        end
        
        function C = finish(THIS)
            br = sprintf('\n');
            C = '\hline';
            if ~THIS.options.long
                C = [C,br,'\end{tabular}}'];
                C = [C,finishwrapper(THIS)];
            else
                C = [C,br,'\end{longtable}}'];
            end
            C = [C,finishsideways(THIS)];
        end
        
        function C = beginwrapper(THIS,space)
            br = sprintf('\n');
            C = ['\begin{tabular}[t]{@{\hspace*{-3pt}}c@{}}',br];
            C = [C,printcaption(THIS,1,'c',space),br];
        end
        
        function C = finishwrapper(THIS) %#ok<MANU>
            br = sprintf('\n');
            C = [br,'\end{tabular}'];
        end
        
        function C = beginsideways(THIS)
            C = '';
            if THIS.options.sideways
                br = sprintf('\n');
                C = [C,br,'\begin{sideways}'];
            end
        end
        
        function C = finishsideways(THIS)
            C = '';
            if THIS.options.sideways
                br = sprintf('\n');
                C = [C,br,'\end{sideways}'];
            end
        end     
        
        function C = colspec(THIS)
            % Create column specs for tabular environment with all columns
            % aligned right and vertical lines inserted at THIS.vline
            % positions.
            C = char('l'*ones(1,THIS.nlead));
            if THIS.ncol == 0
                return
            end
            % Pre-sample vertical line.
            if any(THIS.vline == 0)
                C = [C,'|'];
            end
            THIS.vline(THIS.vline < 1 | THIS.vline > THIS.ncol) = [];
            c1 = char('r'*ones(1,THIS.ncol));
            c2 = char(' '*ones(1,THIS.ncol));
            c2(THIS.vline) = '|';
            c3 = [c1;c2];
            c3 = transpose(c3(:));
            C = [C,c3];
            C(C == char(32)) = '';
        end
        
    end
    
end
