// Copyright 2016 The Bazel Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.testing.coverage;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import org.jacoco.core.analysis.IBundleCoverage;
import org.jacoco.core.analysis.IClassCoverage;
import org.jacoco.core.analysis.ICounter;
import org.jacoco.core.analysis.IMethodCoverage;
import org.jacoco.core.analysis.IPackageCoverage;
import org.jacoco.core.analysis.ISourceFileCoverage;
import org.jacoco.core.data.ExecutionData;
import org.jacoco.core.data.SessionInfo;
import org.jacoco.report.IReportGroupVisitor;
import org.jacoco.report.IReportVisitor;
import org.jacoco.report.ISourceFileLocator;

/**
 * Simple lcov formatter to be used with lcov_merger.par.
 *
 * <p>The lcov format is documented here: http://ltp.sourceforge.net/coverage/lcov/geninfo.1.php
 */
public class JacocoLCOVFormatter {

  public IReportVisitor createVisitor(
      final File output, final Map<String, BranchCoverageDetail> branchCoverageDetail) {
    return new IReportVisitor() {

      private Map<String, Map<String, IClassCoverage>> sourceToClassCoverage = new TreeMap<>();
      private Map<String, ISourceFileCoverage> sourceToFileCoverage = new TreeMap<>();

      @Override
      public void visitInfo(List<SessionInfo> sessionInfos, Collection<ExecutionData> executionData)
          throws IOException {}

      @Override
      public void visitEnd() throws IOException {
        try (FileWriter fileWriter = new FileWriter(output, true);
            PrintWriter printWriter = new PrintWriter(fileWriter)) {
          for (String sourceFile : sourceToClassCoverage.keySet()) {
            processSourceFile(printWriter, sourceFile);
          }
        }
      }

      @Override
      public void visitBundle(IBundleCoverage bundle, ISourceFileLocator locator)
          throws IOException {
        // Jacoco's API is geared towards HTML/XML reports which have a hierarchical nature. The
        // following loop would call the report generators for packages, classes, methods, and
        // finally link the source view (which would be generated by walking the actual source file
        // and annotating the coverage data). For lcov, we don't really need the source file, but
        // we need to output FN/FNDA pairs with method coverage, which means we need to index this
        // information and process everything at the end.
        for (IPackageCoverage pkgCoverage : bundle.getPackages()) {
          for (IClassCoverage clsCoverage : pkgCoverage.getClasses()) {
            String fileName = clsCoverage.getPackageName() + "/" + clsCoverage.getSourceFileName();
            if (!sourceToClassCoverage.containsKey(fileName)) {
              sourceToClassCoverage.put(fileName, new TreeMap<String, IClassCoverage>());
            }
            sourceToClassCoverage.get(fileName).put(clsCoverage.getName(), clsCoverage);
          }
          for (ISourceFileCoverage srcCoverage : pkgCoverage.getSourceFiles()) {
            sourceToFileCoverage.put(
                srcCoverage.getPackageName() + "/" + srcCoverage.getName(), srcCoverage);
          }
        }
      }

      @Override
      public IReportGroupVisitor visitGroup(String name) throws IOException {
        return null;
      }

      private void processSourceFile(PrintWriter writer, String sourceFile) {
        writer.printf("SF:%s\n", sourceFile);

        ISourceFileCoverage srcCoverage = sourceToFileCoverage.get(sourceFile);
        if (srcCoverage != null) {
          // List methods, including methods from nested classes, in FN/FNDA pairs
          for (IClassCoverage clsCoverage : sourceToClassCoverage.get(sourceFile).values()) {
            for (IMethodCoverage mthCoverage : clsCoverage.getMethods()) {
              String name = constructFunctionName(mthCoverage, clsCoverage.getName());
              writer.printf("FN:%d,%s\n", mthCoverage.getFirstLine(), name);
              writer.printf("FNDA:%d,%s\n", mthCoverage.getMethodCounter().getCoveredCount(), name);
            }
          }

          for (IClassCoverage clsCoverage : sourceToClassCoverage.get(sourceFile).values()) {
            BranchCoverageDetail detail = branchCoverageDetail.get(clsCoverage.getName());
            if (detail != null) {
              for (int line : detail.linesWithBranches()) {
                int numBranches = detail.getBranches(line);
                boolean executed = detail.getExecutedBit(line);
                if (executed) {
                  for (int branchIdx = 0; branchIdx < numBranches; branchIdx++) {
                    if (detail.getTakenBit(line, branchIdx)) {
                      writer.printf("BA:%d,%d\n", line, 2); // executed, taken
                    } else {
                      writer.printf("BA:%d,%d\n", line, 1); // executed, not taken
                    }
                  }
                } else {
                  for (int branchIdx = 0; branchIdx < numBranches; branchIdx++) {
                    writer.printf("BA:%d,%d\n", line, 0); // not executed
                  }
                }
              }
            }
          }

          // List of DA entries matching source lines
          int firstLine = srcCoverage.getFirstLine();
          int lastLine = srcCoverage.getLastLine();
          for (int line = firstLine; line <= lastLine; line++) {
            ICounter instructionCounter = srcCoverage.getLine(line).getInstructionCounter();
            if (instructionCounter.getTotalCount() != 0) {
              writer.printf("DA:%d,%d\n", line, instructionCounter.getCoveredCount());
            }
          }
        }
        writer.println("end_of_record");
      }

      private String constructFunctionName(IMethodCoverage mthCoverage, String clsName) {
        // The lcov spec doesn't of course cover Java formats, so we output the method signature.
        // lcov_merger doesn't seem to care about these entries.
        return clsName + "::" + mthCoverage.getName() + " " + mthCoverage.getDesc();
      }
    };
  }
}
