%

%   Copyright 2013-2018 The MathWorks, Inc.

classdef (Abstract = true) CGTSection  < handle
    properties
        parsedSection % parsed Section content
        style = coder.BannerStyle.classic; % Section Style
        width = 80; % Section Width
        isCustom = 0;
    end
    
    methods
        function obj = CGTSection(style, width)
            obj.style = style;
            obj.width = width;
        end
    end
    
    methods
        function obj = setIsCustomSection(obj)
            obj.isCustom = 1;
        end
        
        function parseSection(obj, rawSection, tokenRepository)
            % parses Section and replaces tokens with their values
            lines = regexp(rawSection, '\n', 'split');
            obj.parsedSection = [];
            if (length(lines) > 2)
                sectionContent = lines(2:end-1);
                % Skip the first line as its the Section Name
                i = 1;
                while i <= length(sectionContent)
                    % Split up each line
                    locations = regexp(sectionContent{i},'\s','split');
                    j = 1;
                    isTokenEmpty = false;
                    while j <= length(locations)
                        if ~isempty(locations{j})
                            % Check for tokens in the current sub-string.
                            % Strip it and capture the token.
                            temp = regexp(locations{j}, '%<[^\s]*>', 'match');
                            if(~isempty(temp))
                                token = temp{1}(3:end-1);
                                % Check if it is token or a callback:
                                callbackToken = token(1);
                                if(callbackToken == '@' || callbackToken == '!')
                                    if(callbackToken == '!')
                                       DAStudio.warning('RTW:buildProcess:InvalidCGTToken'); 
                                    end
                                    
                                    % It is a callback
                                    token = token(2:end);
                                    tokenValue = tokenRepository.executeCallback(token);
                                    
                                    if(isempty(tokenValue))
                                       tokenValue = [callbackToken token];
                                    end
                                else
                                    % replace token with actual value:
                                    tokenValue = tokenRepository.getTokenValue(token); %#ok<*AGROW>
                                end
                                % We do not support '\t' in tokens. Replace with
                                % space '\s'
                                tokenValue = strrep(tokenValue,char(9),char(32));
                                tokenValue = strtrim(tokenValue);
                                % Check if token is empty.
                                if(isempty(tokenValue) || all(isspace(tokenValue)))
                                    isTokenEmpty = true;
                                end
                                
                                % Format the output token
                                % 1.) See if it has multiple lines and format it
                                % 2.) Ensure it is placed in correct location in
                                % the sub-string
                                i_start = strfind(locations{j},'%');
                                i_end = strfind(locations{j},'>');
                                
                                % Step 1: Handling Multiline Tokens
                                % We only need to perform alignment if this
                                % multiline token is not the first token on this
                                % line. Check for that using (j>1) condition.
                                multiline = regexp(tokenValue,'\n','split');
                                if((length(multiline)>1) && (j>1))
                                    tempStr = regexp(strjoin(locations(1:j-1),' '),'\n','split');
                                    positionForAlign = length(tempStr{end}) + (i_start);
                                    for k=2:length(multiline)
                                        multiline{k} = sprintf([repmat(char(32),1,positionForAlign) '%s'],multiline{k});
                                    end
                                    tokenValue = strjoin(multiline,'\n');
                                end
                                
                                % Step 2: Ensure correct placement 
                                locations{j} = sprintf('%s%s%s',locations{j}(1:i_start-1),tokenValue,locations{j}(i_end+1:end));
                                
                            end
                            %
                        end
                        j = j+1;
                    end
                    % Put the line back together again
                    sectionContent{i} = strjoin(locations,' ');
                    % If only spaces in the line and the line contained a token
                    % which reduced to space or empty, simply delete the whole
                    % line. g1018520
                    if(all(isspace(sectionContent{i})) && isTokenEmpty)
                        sectionContent(i) = [];
                    else  % Increment counter only if line is not deleted.
                        i = i+1;
                    end
                end
                % Put the section content together
                obj.parsedSection = strjoin(sectionContent,'\n');
            end
            % prepend watermark for non-professional use
            if(isa(obj,'coder.codeTemplate.FileBannerSection') && ~isempty(emit(coder.internal.watermark)))
                    obj.parsedSection = sprintf('%s\n%s',emit(coder.internal.watermark), obj.parsedSection);
            end
        end
        
        function stringEmitted =  emitSection(obj)
            % The parsedSection String can be emitted using the specified style for the section
            stringEmitted = [];
            if isempty(obj.parsedSection)
                return
            end
            lines = regexp(obj.parsedSection, '\n', 'split');
            isSingleLine = length(lines) == 1;
            isUserDefined = obj.isCustom;
            % Ignore a section banner if it contains only spaces
            if (all(isspace(obj.parsedSection)))
                return
            end
            switch obj.style
                case coder.BannerStyle.classic
                    if(isSingleLine)
                        stringEmitted = sprintf('/* %s */ \n', obj.parsedSection);
                    elseif(isUserDefined)
                        for i=1:length(lines)
                            stringEmitted = sprintf('%s %s \n', stringEmitted, lines{i});
                        end
                    else
                        stringEmitted = sprintf('/* \n');
                        for i=1:length(lines)
                            stringEmitted = sprintf('%s * %s \n', stringEmitted, lines{i});
                        end
                        stringEmitted = sprintf('%s */\n', stringEmitted);
                    end
                case coder.BannerStyle.classic_cpp
                    if(isSingleLine)
                        stringEmitted = sprintf('// %s \n', obj.parsedSection);
                    else
                        stringEmitted = sprintf('// \n');
                        for i=1:length(lines)
                            stringEmitted = sprintf('%s// %s \n', stringEmitted, lines{i});
                        end
                        stringEmitted = sprintf('%s//\n', stringEmitted);
                    end
                case coder.BannerStyle.box
                    stringEmitted = sprintf('/%s/\n',repmat('*',1,obj.width-2));
                    for i=1:length(lines)
                        lineLength = length(slsvInternal('slsvEscapeServices','unicode2native',lines{i}));
                        emptySpaceToBeFilled = obj.width - (lineLength + 6);
                        spacer = '';
                        if emptySpaceToBeFilled > 0
                            spacer = repmat(' ',1,emptySpaceToBeFilled);
                        end
                        stringEmitted = sprintf('%s/* %s%s */\n',stringEmitted, lines{i}, spacer);
                    end
                    stringEmitted = sprintf('%s/%s/\n',stringEmitted, repmat('*',1,obj.width-2));
                case coder.BannerStyle.box_cpp
                    stringEmitted = sprintf('//%s//\n',repmat('/',1,obj.width-4));
                    for i=1:length(lines)
                        lineLength = length(slsvInternal('slsvEscapeServices','unicode2native',lines{i}));
                        emptySpaceToBeFilled = obj.width - (lineLength + 6);
                        spacer = '';
                        if emptySpaceToBeFilled > 0
                            spacer = repmat(' ',1,emptySpaceToBeFilled);
                        end
                        stringEmitted = sprintf('%s// %s%s //\n',stringEmitted, lines{i}, spacer);
                    end
                    stringEmitted = sprintf('%s//%s//\n',stringEmitted, repmat('/',1,obj.width-4));
                case coder.BannerStyle.open_box
                    stringEmitted = sprintf('/%s\n',repmat('*',[1,obj.width-1]));
                    for i=1:length(lines)
                        stringEmitted = sprintf('%s * %s\n',stringEmitted, lines{i});
                    end
                    stringEmitted = sprintf('%s %s/\n',stringEmitted, repmat('*',[1,obj.width-2]));
                case coder.BannerStyle.open_box_cpp
                    stringEmitted = sprintf('//%s//\n',repmat('/',[1,obj.width-4]));
                    for i=1:length(lines)
                        stringEmitted = sprintf('%s// %s\n',stringEmitted, lines{i});
                    end
                    stringEmitted = sprintf('%s%s\n',stringEmitted, repmat('/',[1,obj.width]));
                case coder.BannerStyle.doxygen
                    if(isSingleLine)
                        stringEmitted = sprintf('/** %s */ \n', obj.parsedSection);
                    else
                        stringEmitted = sprintf('/** \n');
                        for i=1:length(lines)
                            stringEmitted = sprintf('%s * %s \n', stringEmitted, lines{i});
                        end
                        stringEmitted = sprintf('%s */\n', stringEmitted);
                    end
                case coder.BannerStyle.doxygen_qt
                    if(isSingleLine)
                        stringEmitted = sprintf('/*! %s */ \n', obj.parsedSection);
                    else
                        stringEmitted = sprintf('/*! \n');
                        for i=1:length(lines)
                            stringEmitted = sprintf('%s * %s \n', stringEmitted, lines{i});
                        end
                        stringEmitted = sprintf('%s */\n', stringEmitted);
                    end
                case coder.BannerStyle.doxygen_cpp
                    if(isSingleLine)
                        stringEmitted = sprintf('/// %s \n', obj.parsedSection);
                    else
                        stringEmitted = sprintf('/// \n');
                        for i=1:length(lines)
                            stringEmitted = sprintf('%s/// %s \n', stringEmitted, lines{i});
                        end
                        stringEmitted = sprintf('%s///\n', stringEmitted);
                    end
                case coder.BannerStyle.doxygen_qt_cpp
                    if(isSingleLine)
                        stringEmitted = sprintf('//! %s \n', obj.parsedSection);
                    else
                        stringEmitted = sprintf('//! \n');
                        for i=1:length(lines)
                            stringEmitted = sprintf('%s//! %s \n', stringEmitted, lines{i});
                        end
                        stringEmitted = sprintf('%s//!\n', stringEmitted);
                    end
            end
        end
        
    end
    
    
end
