// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Text;   // Used for StringBuilder class.
using System.IO;     // Used for SteamWriter class.


namespace TraceabilityTool
{

    // This class is responsible for writing reports generated by ReportGenerator class to files in CSV format.
    class CSVReportWriter
    {
        
        public static void WriteTraceabilityReport(string outputFolderPath)
        {
            StringBuilder sb = new StringBuilder();

            // Print table header.
            sb.AppendLine("Requirement ID,,File Name,Line Number");

            // Check every requiremend ID extracted from requirement documents.
            foreach (string key in ReportGenerator.reqDocLookup.Keys)
            {
                // Print requirement ID and the path of the document defining it.
                sb.AppendLine(key + ",Defined in," + ReportGenerator.reqDocLookup[key]);

                // Print source code file paths
                if (ReportGenerator.reqCodeMatrix.ContainsKey(key))
                {
                    foreach (FilePathLineNum reqData in ReportGenerator.reqCodeMatrix[key])
                    {
                        sb.AppendLine(key + ",Coded in," + reqData.filePath + "," + reqData.lineNum.ToString());
                    }
                }
                else
                {
                    sb.AppendLine(key + ",Not coded," + Path.GetFileName(ReportGenerator.reqDocLookup[key]));
                }

                // Print test code file paths
                if (ReportGenerator.reqTestMatrix.ContainsKey(key))
                {
                    foreach (FilePathLineNum reqData in ReportGenerator.reqTestMatrix[key])
                    {
                        sb.AppendLine(key + ",Tested in," + reqData.filePath + "," + reqData.lineNum.ToString());
                    }
                }
                else
                {
                    sb.AppendLine(key + ",Not tested," + Path.GetFileName(ReportGenerator.reqDocLookup[key]));
                }
            }

            // Print totals
            sb.AppendLine("Total unique requirements,"        + ReportGenerator.reqDocLookup.Count.ToString());
            sb.AppendLine("Total implemented requirements,"   + ReportGenerator.reqCodeMatrix.Count.ToString());
            sb.AppendLine("Total tested requirements,"        + ReportGenerator.reqTestMatrix.Count.ToString());
            sb.AppendLine("Total unimplemented requirements," + ReportGenerator.missingCodeCoverage.Count.ToString());
            sb.AppendLine("Total untested requirements,"      + ReportGenerator.missingTestCoverage.Count.ToString());

            // Output data to a CSV file.
            ReportWriter.writeStringToFile(sb.ToString(), outputFolderPath + @"\traceability_matrix.csv");
        }


        public static void WriteMissingReqReport(string outputFolderPath)
        {
            StringBuilder sb = new StringBuilder();
            int count = 0;

            // Print table header.
            sb.AppendLine("Requirement ID,Reason,Found in,Line Number");

            // Find all requirements with invalid identfiers in code or tests.
            foreach (string key in ReportGenerator.invalidRequirements.Keys)
            {
                foreach (InvalidReqDictEntry entry in ReportGenerator.invalidRequirements[key])
                {
                    sb.AppendLine(key + "," + entry.reason + "," + entry.filePath + "," + entry.lineNum.ToString());
                }
            }

            // Find all requirements not covered in code.
            foreach (string key in ReportGenerator.missingCodeCoverage.Keys)
            {
                // Check if the requirement is also not covered in tests.
                if (ReportGenerator.missingTestCoverage.ContainsKey(key))
                {
                    sb.AppendLine(key + ",Not coded and not tested," + ReportGenerator.missingCodeCoverage[key]);
                    count++;
                }
                else
                {
                    sb.AppendLine(key + ",Not coded," + ReportGenerator.missingCodeCoverage[key]);
                }
            }

            // Find all the requirements not covered in tests.
            foreach (string key in ReportGenerator.missingTestCoverage.Keys)
            {
                // Ignore the requirements that we already found missing in code.
                if (!ReportGenerator.missingCodeCoverage.ContainsKey(key))
                {
                    sb.AppendLine(key + ",Not tested," + ReportGenerator.missingTestCoverage[key]);
                }
            }

            sb.AppendLine("Total invalid requirements found in code and tests," + ReportGenerator.invalidRequirements.Count.ToString());
            sb.AppendLine("Total unimplemented requirements," + ReportGenerator.missingCodeCoverage.Count.ToString());
            sb.AppendLine("Total untested requirements," + ReportGenerator.missingTestCoverage.Count.ToString());
            sb.AppendLine("Total requirements missing both implementation and tests," + count.ToString());

            // Output data to a CSV file.
            ReportWriter.writeStringToFile(sb.ToString(), outputFolderPath + @"\missing_requirements.csv");
        }


        public static void WriteRepeatingReqReport(string outputFolderPath)
        {
            StringBuilder sb = new StringBuilder();

            // Print table header.
            sb.AppendLine("Requirement ID,Found in File");

            foreach (string key in ReportGenerator.repeatingRequirements.Keys)
            {
                foreach (string reqDocPath in ReportGenerator.repeatingRequirements[key])
                {
                    sb.AppendLine(key + "," + reqDocPath);
                }
            }

            sb.AppendLine("Total repeating requirements," + ReportGenerator.repeatingRequirements.Count.ToString());

            // Output data to a CSV file.
            ReportWriter.writeStringToFile(sb.ToString(), outputFolderPath + @"\repeating_requirements.csv");
        }

    }
}
