classdef HTMLAppendSummaryTable < mlreportgen.dom.DocumentPart
    %HTMLAPPENDSUMMARYTABLE Create and append header part of report.
    %   HTMLAPPENDSUMMARYTABLE Append report title and table correspondent
    %   to the following:
    %
    %       Design Review for Model Predictive Controller <mpcObj> 
    %       
    %       Summary of Performed Tests
    %                   Test	                    Status
    %           MPC Object Creation                 <icon(s)>
    %           QP Hessian Matrix Validity	        <icon(s)>
    %           Closed-Loop Internal Stability	    <icon(s)>
    %           Closed-Loop Nominal Stability	    <icon(s)>
    %           Closed-Loop Steady-State Gains	    <icon(s)>
    %           Hard MV Constraints	                <icon(s)>
    %           Other Hard Constraints              <icon(s)>
    %           Soft Constraints	                <icon(s)>
    %           Memory Size for MPC Data	        <icon(s)>


    %   Author: Eri Gualter
    %   Copyright 2022 MathWorks, Inc.

    properties
        %REPORTDATA
        ReportData

        %TESTLINKID
        TestLinkID
    end

    properties (Constant)
        %ICONDIRDICTIONARY
        IconDirDictionary = mpcreview.HTMLAppendSummaryTable.getIconDirDictionary;
    end

    methods
        function obj = HTMLAppendSummaryTable(rpt)
            %HTMLAPPENDSUMMARYTABLE Constructor

            % Call mlreportgen.dom.DocumentPart constructor
            obj@mlreportgen.dom.DocumentPart(rpt.Type, rpt.TemplatePath, 'Header');

            obj.ReportData = rpt.ReportData;
        end
    end

    methods
        function fillReportTitle(obj)
            %% Append MainTitle

            % Extract message ID for report title
            titleMsgID      = obj.ReportData.ReportTitles.MainTitle;
            tilleMsgIDparam = obj.ReportData.MpcName;
            if ~isempty(tilleMsgIDparam)
                tilleMsgIDparam = sprintf("<tt>'%s'</tt>",tilleMsgIDparam);
            end

            maintTitleTxt = mpcreview.HTMLTag.getString({titleMsgID,tilleMsgIDparam});
            maintTitleTxt = sprintf("<span class='titleReport'>%s</span>",maintTitleTxt);
            maintTitleDom = mlreportgen.dom.RawText(maintTitleTxt);

            % Append DOM Elements
            obj.append(maintTitleDom);
        end

        function fillTableTitle(obj)
            %% Append Summary Title

            import mlreportgen.dom.*
            import mlreportgen.utils.*

            headingDom = mpcreview.HTMLTag.appendHeading([], ...
                mpcreview.EnumTag.AddHeading1,...
                obj.ReportData.ReportTitles.SummarySubTitle);

            summaryRef = normalizeLinkID('summary');
            headingDom.append(LinkTarget(summaryRef));

            append(obj, headingDom);
        end
        
        function fillSummaryTable(obj)
            %% Append Summary Table

            import mlreportgen.dom.*;
            import mlreportgen.utils.*

            % Get 9-by-2 table content: {Title, Status} 
            [~, idxEnum] = obj.ReportData.getStatusResults;
            testTitles = cell(9,2);
            for iTest = 1:9
                titleStr = obj.ReportData.Test(iTest).Title;
                testTitles{iTest, 1} = mpcreview.HTMLTag.getString(titleStr);
                testTitles{iTest, 2} = char(idxEnum(iTest));
            end

            % Create DOM Table object
            summaryTable = mlreportgen.dom.Table();
            summaryTable.StyleName = 'summaryTable2';
            summaryTable.TableEntriesInnerMargin = '2px';

            % Extract headers string from catalag
            headerTest = ctrlMsgUtils.message('MPC:object:ReviewHeaderTest');
            headerStatus = ctrlMsgUtils.message('MPC:object:ReviewHeaderStatus');

            % Append Table header
            summaryHeader  = mlreportgen.dom.TableRow();
            entrySummaryH1 = mlreportgen.dom.TableHeaderEntry(headerTest);
            entrySummaryH2 = mlreportgen.dom.TableHeaderEntry(headerStatus);
            entrySummaryH2.ColSpan = 4;
            entrySummaryH2.Style = {HAlign("center")};

            summaryHeader.append(entrySummaryH1);
            summaryHeader.append(entrySummaryH2);
            summaryTable.append(summaryHeader);

            % Append Table rows
            ref = cell(length(obj.ReportData.Test),1);
            for it = 1:length(obj.ReportData.Test)
                ref{it} = normalizeLinkID(obj.ReportData.Test(it).Title);
                txtLink = InternalLink(ref{it}, testTitles{it,1});

                tbEntry = mlreportgen.dom.TableEntry();
                rowSumm = mlreportgen.dom.TableRow();

                tbEntry.append(txtLink);
                rowSumm.append(tbEntry);

                if isempty(obj.ReportData.Test(it).Children)
                    tStatus = obj.ReportData.Test(it).Status;
                    svgIcon = obj.IconDirDictionary(tStatus);

                    % to enhance: Add InternalLink to ImageArea. Waiting for g1575210
                    iconArea = ImageArea(strcat('#',txtLink.Target), char(tStatus), 10, 10, 10);
                    iconMap  = ImageMap();
                    iconMap.append(iconArea);

                    domIcon = mlreportgen.dom.Image(svgIcon{1});
                    domIcon.Height = '20px';
                    domIcon.Width  = '20px';
                    domIcon.Map = iconMap;
                    rowSumm.append(TableEntry(domIcon));

                    summaryTable.append(rowSumm);

                    % Only generate full report if MPC initialization Pass
                    if obj.ReportData.Test(1).Status == mpcreview.EnumStatus.Fail
                        break;
                    else
                        continue;
                    end
                end

                nChildren = length(obj.ReportData.Test(it).Children);
                domIcon = cell(nChildren,1);
                for itc = 1:length(obj.ReportData.Test(it).Children)
                    subtest = obj.ReportData.Test(it).Children(itc);
                    svgIcon = obj.IconDirDictionary(subtest.Status);
                    
                    tmpref = normalizeLinkID(subtest.Title);
                    iconArea = ImageArea(strcat('#',tmpref),char(subtest.Status),10,10,10);
                    iconMap  = ImageMap();
                    append(iconMap,iconArea);

                    domIcon{itc} = mlreportgen.dom.Image(svgIcon{1});
                    domIcon{itc}.Height = '20px';
                    domIcon{itc}.Width  = '20px';
                    domIcon{itc}.Map = iconMap;
                    rowSumm.append(TableEntry(domIcon{itc}));

                end
                summaryTable.append(rowSumm);
            end
            obj.TestLinkID = ref;

            % Append DOM Elements
            obj.append(summaryTable);
        end
    end

    methods (Static)
        function iconDictionary = getIconDirDictionary(~)
            %GETICONDIRDICTIONARY Return dictionary object that maps
            % unique keys to icon file's name. 
            %
            %   Example:
            %       import mpcreview.*
            %       dict = HTMLAppendSummaryTable.getIconDirDictionary;
            %       flag = mpcreview.EnumStatus.Fail;
            %       path = dict(flag)

            dirClass = mpcreview.BaseReport.getClassFolder();
            dirIcons = fullfile(dirClass,'resources','templates','icons');

            iconFileList   = {...
                fullfile(dirIcons,'error.svg');
                fullfile(dirIcons,'warning.svg');
                fullfile(dirIcons,'success.svg');
                fullfile(dirIcons,'help.svg')};

            enumStatusList = [...
                mpcreview.EnumStatus.Fail;
                mpcreview.EnumStatus.Warning;
                mpcreview.EnumStatus.Pass;
                mpcreview.EnumStatus.Unknown];

            iconDictionary = dictionary(enumStatusList, iconFileList);
        end
    end
end