<commit_before>﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using BugReport.Util;
using BugReport.DataModel;
using BugReport.Query;

namespace BugReport.Reports
{
    public class HtmlReport : Report
    {
        private Config _config;
        private IEnumerable<NamedQuery> _areaLabelQueries;

        public HtmlReport(IEnumerable<string> configFiles)
        {
            _config = new Config(configFiles);

            _areaLabelQueries = _config.AreaLabels
                .Select(label => new NamedQuery(label.Name, new ExpressionLabel(label.Name)))
                .ToList();
        }

        public void Write(IEnumerable<string> beginFiles, IEnumerable<string> endFiles, string outputHtmlFile)
        {
            IEnumerable<DataModelIssue> beginIssuesAll = IssueCollection.LoadIssues(beginFiles, _config);
            IEnumerable<DataModelIssue> endIssuesAll = IssueCollection.LoadIssues(endFiles, _config);

            IEnumerable<DataModelIssue> beginIssues = beginIssuesAll.Where(i => i.IsIssueOrComment).ToArray();
            IEnumerable<DataModelIssue> endIssues = endIssuesAll.Where(i => i.IsIssueOrComment).ToArray();
            using (StreamWriter file = new StreamWriter(outputHtmlFile))
            {
                file.WriteLine("<html><body>");
                file.WriteLine($"Report create on {DateTime.Now}<br/>");

                file.WriteLine("/begin");
                file.WriteLine("<ul>");
                foreach (string fileName in beginFiles)
                {
                    file.WriteLine($"    <li>{fileName}</li>");
                }
                file.WriteLine("</ul>");

                file.WriteLine("/end");
                file.WriteLine("<ul>");
                foreach (string fileName in endFiles)
                {
                    file.WriteLine($"    <li>{fileName}</li>");
                }
                file.WriteLine("</ul>");

                file.WriteLine("<h2>Alerts - sorted by issue count</h2>");
                NamedQuery firstQuery = _config.Queries.First();
                Report(file, 
                    beginIssues, 
                    endIssues, 
                    _config.Queries, 
                    _config.Alerts.OrderByDescending(alert => 
                        Expression.And(alert.Query, firstQuery.Query).Evaluate(endIssues).Count()));

                file.WriteLine("<h2>Teams</h2>");
                Report(file,
                    beginIssues,
                    endIssues,
                    _config.Queries,
                    _config.Teams.Select(
                        team =>
                        new NamedQuery(
                            team.Name,
                            Expression.Or(
                                _config.Alerts.Where(alert => alert.Team == team)
                                    .Select(alert => alert.Query)))));

                file.WriteLine("<h2>Organizations</h2>");
                Report(file,
                    beginIssues,
                    endIssues,
                    _config.Queries,
                    _config.Organizations.Select(
                        org =>
                        new NamedQuery(
                            org.Description,
                            Expression.Or(
                                _config.Alerts.Where(alert => alert.IsOrganization(org))
                                    .Select(alert => alert.Query)))));

                file.WriteLine("<h2>Alerts - sorted alphabetically</h2>");
                Report(file, 
                    beginIssues, 
                    endIssues, 
                    _config.Queries, 
                    _config.Alerts.OrderBy(alert => alert.Name));

                file.WriteLine("<h2>Areas - sorted alphabetically</h2>");
                Report(file, 
                    beginIssues, 
                    endIssues, 
                    _config.Queries, 
                    _areaLabelQueries.OrderBy(labelQuery => labelQuery.Name));

                /*
                file.WriteLine("<h2>Alerts - sorted alphabetically (no links)</h2>");
                Report(file, 
                    beginIssues, 
                    endIssues, 
                    _config.Queries, 
                    _config.Alerts.OrderBy(alert => alert.Name), 
                    shouldHyperLink: false);

                file.WriteLine("<h2>Areas - sorted alphabetically (no links)</h2>");
                Report(file, 
                    beginIssues, 
                    endIssues, 
                    _config.Queries, 
                    _areaLabelQueries.OrderBy(labelQuery => labelQuery.Name),
                    shouldHyperLink: false);
                */

                file.WriteLine("</body></html>");
            }
        }

        public void Report(
            StreamWriter file,
            IEnumerable<DataModelIssue> beginIssues,
            IEnumerable<DataModelIssue> endIssues,
            IEnumerable<NamedQuery> columns,
            IEnumerable<NamedQuery> rows,
            bool shouldHyperLink = true)
        {
            file.WriteLine("<table border=\"1\">");
            file.WriteLine("<tr>");
            ReportTableRow(file, "  ", 
                "&nbsp;", 
                columns.SelectMany(col => new string[] {
                    $"<b>{col.Name}</b>",
                    "<i>(diff)</i>",
                    "<i>(new)</i>",
                    "<i>(gone)</i>" } ));
            file.WriteLine("</tr>");

            foreach (NamedQuery row in rows)
            {
                file.WriteLine("<tr>");
                ReportTableRow(file, "  ",
                    $"<b>{row.Name}</b>",
                    columns.SelectMany(col =>
                    {
                        FilteredIssues filteredIssues = new FilteredIssues(
                            Expression.And(row.Query, col.Query),
                            beginIssues,
                            endIssues);
                        return new string[] {
                            GetQueryCountLinked(
                                filteredIssues.Query, 
                                filteredIssues.End, 
                                shouldHyperLink, 
                                useRepositoriesFromIssues: true),
                            $"<i>{(filteredIssues.End.Count() - filteredIssues.Begin.Count()).ToString("+#;-#;0")}</i>",
                            $"<i>+{filteredIssues.EndOnly.Count()}</i>",
                            $"<i>-{filteredIssues.BeginOnly.Count()}</i>" };
                    }));
                file.WriteLine("</tr>");
            }

            Expression noRowQuery = Expression.And(rows.Select(row => Expression.Not(row.Query)).ToArray());
            file.WriteLine("<tr>");
            ReportTableRow(file, "  ",
                "<b>Other (missing above)</b>",
                columns.SelectMany(col =>
                {
                    FilteredIssues filteredIssues = new FilteredIssues(<commit_msg>Add tooltips with queries to row and column headers<commit_after>﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using BugReport.Util;
using BugReport.DataModel;
using BugReport.Query;

namespace BugReport.Reports
{
    public class HtmlReport : Report
    {
        private Config _config;
        private IEnumerable<NamedQuery> _areaLabelQueries;

        public HtmlReport(IEnumerable<string> configFiles)
        {
            _config = new Config(configFiles);

            _areaLabelQueries = _config.AreaLabels
                .Select(label => new NamedQuery(label.Name, new ExpressionLabel(label.Name)))
                .ToList();
        }

        public void Write(IEnumerable<string> beginFiles, IEnumerable<string> endFiles, string outputHtmlFile)
        {
            IEnumerable<DataModelIssue> beginIssuesAll = IssueCollection.LoadIssues(beginFiles, _config);
            IEnumerable<DataModelIssue> endIssuesAll = IssueCollection.LoadIssues(endFiles, _config);

            IEnumerable<DataModelIssue> beginIssues = beginIssuesAll.Where(i => i.IsIssueOrComment).ToArray();
            IEnumerable<DataModelIssue> endIssues = endIssuesAll.Where(i => i.IsIssueOrComment).ToArray();
            using (StreamWriter file = new StreamWriter(outputHtmlFile))
            {
                file.WriteLine("<html><body>");
                file.WriteLine($"Report create on {DateTime.Now}<br/>");

                file.WriteLine("/begin");
                file.WriteLine("<ul>");
                foreach (string fileName in beginFiles)
                {
                    file.WriteLine($"    <li>{fileName}</li>");
                }
                file.WriteLine("</ul>");

                file.WriteLine("/end");
                file.WriteLine("<ul>");
                foreach (string fileName in endFiles)
                {
                    file.WriteLine($"    <li>{fileName}</li>");
                }
                file.WriteLine("</ul>");

                file.WriteLine("<h2>Alerts - sorted by issue count</h2>");
                NamedQuery firstQuery = _config.Queries.First();
                Report(file, 
                    beginIssues, 
                    endIssues, 
                    _config.Queries, 
                    _config.Alerts.OrderByDescending(alert => 
                        Expression.And(alert.Query, firstQuery.Query).Evaluate(endIssues).Count()));

                file.WriteLine("<h2>Teams</h2>");
                Report(file,
                    beginIssues,
                    endIssues,
                    _config.Queries,
                    _config.Teams.Select(
                        team =>
                        new NamedQuery(
                            team.Name,
                            Expression.Or(
                                _config.Alerts.Where(alert => alert.Team == team)
                                    .Select(alert => alert.Query)))));

                file.WriteLine("<h2>Organizations</h2>");
                Report(file,
                    beginIssues,
                    endIssues,
                    _config.Queries,
                    _config.Organizations.Select(
                        org =>
                        new NamedQuery(
                            org.Description,
                            Expression.Or(
                                _config.Alerts.Where(alert => alert.IsOrganization(org))
                                    .Select(alert => alert.Query)))));

                file.WriteLine("<h2>Alerts - sorted alphabetically</h2>");
                Report(file, 
                    beginIssues, 
                    endIssues, 
                    _config.Queries, 
                    _config.Alerts.OrderBy(alert => alert.Name));

                file.WriteLine("<h2>Areas - sorted alphabetically</h2>");
                Report(file, 
                    beginIssues, 
                    endIssues, 
                    _config.Queries, 
                    _areaLabelQueries.OrderBy(labelQuery => labelQuery.Name));

                /*
                file.WriteLine("<h2>Alerts - sorted alphabetically (no links)</h2>");
                Report(file, 
                    beginIssues, 
                    endIssues, 
                    _config.Queries, 
                    _config.Alerts.OrderBy(alert => alert.Name), 
                    shouldHyperLink: false);

                file.WriteLine("<h2>Areas - sorted alphabetically (no links)</h2>");
                Report(file, 
                    beginIssues, 
                    endIssues, 
                    _config.Queries, 
                    _areaLabelQueries.OrderBy(labelQuery => labelQuery.Name),
                    shouldHyperLink: false);
                */

                file.WriteLine("</body></html>");
            }
        }

        public void Report(
            StreamWriter file,
            IEnumerable<DataModelIssue> beginIssues,
            IEnumerable<DataModelIssue> endIssues,
            IEnumerable<NamedQuery> columns,
            IEnumerable<NamedQuery> rows,
            bool shouldHyperLink = true)
        {
            file.WriteLine("<table border=\"1\">");
            file.WriteLine("<tr>");
            ReportTableRow(file, "  ", 
                "&nbsp;", 
                columns.SelectMany(col => new string[] {
                    $"<b title=\"{col.Query.ToString()}\">{col.Name}</b>",
                    "<i>(diff)</i>",
                    "<i>(new)</i>",
                    "<i>(gone)</i>" } ));
            file.WriteLine("</tr>");

            foreach (NamedQuery row in rows)
            {
                file.WriteLine("<tr>");
                ReportTableRow(file, "  ",
                    $"<b title=\"{row.ToString()}\">{row.Name}</b>",
                    columns.SelectMany(col =>
                    {
                        FilteredIssues filteredIssues = new FilteredIssues(
                            Expression.And(row.Query, col.Query),
                            beginIssues,
                            endIssues);
                        return new string[] {
                            GetQueryCountLinked(
                                filteredIssues.Query, 
                                filteredIssues.End, 
                                shouldHyperLink, 
                                useRepositoriesFromIssues: true),
                            $"<i>{(filteredIssues.End.Count() - filteredIssues.Begin.Count()).ToString("+#;-#;0")}</i>",
                            $"<i>+{filteredIssues.EndOnly.Count()}</i>",
                            $"<i>-{filteredIssues.BeginOnly.Count()}</i>" };
                    }));
                file.WriteLine("</tr>");
            }

            Expression noRowQuery = Expression.And(rows.Select(row => Expression.Not(row.Query)).ToArray());
            file.WriteLine("<tr>");
            ReportTableRow(file, "  ",
                "<b>Other (missing above)</b>",
                columns.SelectMany(col =>
                {
                    FilteredIssues filteredIssues = new FilteredIssues(
{'fraction_non_alphanumeric': 0.11122792262405383, 'fraction_numerical': 0.00224278104850014, 'mean_word_length': 1.2534744156664561, 'pattern_counts': {'":': 0, '<': 129, '<?xml version=': 0, '>': 165, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '515461', 'n_tokens_mistral': 3629, 'n_tokens_neox': 3327, 'n_words': 531}