// Copyright 2018 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.devtools.lcovmerger;

import static com.google.devtools.lcovmerger.Constants.BA_MARKER;
import static com.google.devtools.lcovmerger.Constants.BRDA_MARKER;
import static com.google.devtools.lcovmerger.Constants.BRF_MARKER;
import static com.google.devtools.lcovmerger.Constants.BRH_MARKER;
import static com.google.devtools.lcovmerger.Constants.DA_MARKER;
import static com.google.devtools.lcovmerger.Constants.DELIMITER;
import static com.google.devtools.lcovmerger.Constants.END_OF_RECORD_MARKER;
import static com.google.devtools.lcovmerger.Constants.FNDA_MARKER;
import static com.google.devtools.lcovmerger.Constants.FNF_MARKER;
import static com.google.devtools.lcovmerger.Constants.FNH_MARKER;
import static com.google.devtools.lcovmerger.Constants.FN_MARKER;
import static com.google.devtools.lcovmerger.Constants.LF_MARKER;
import static com.google.devtools.lcovmerger.Constants.LH_MARKER;
import static com.google.devtools.lcovmerger.Constants.SF_MARKER;
import static com.google.devtools.lcovmerger.Constants.TAKEN;
import static java.nio.charset.StandardCharsets.UTF_8;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * A parser for the lcov tracefile format used by geninfo. See
 * <a href="http://ltp.sourceforge.net/coverage/lcov/geninfo.1.php"> lcov documentation</a>
 */
class LcovParser {

  private static final Logger logger = Logger.getLogger(LcovParser.class.getName());
  private final InputStream inputStream;
  private SourceFileCoverage currentSourceFileCoverage;

  private LcovParser(InputStream inputStream) {
    this.inputStream = inputStream;
  }

  public static List<SourceFileCoverage> parse(InputStream inputStream) throws IOException {
    return new LcovParser(inputStream).parse();
  }

  /**
   * Reads the tracefile line by line and creates a SourceFileCoverage object
   * for each section of the file between a SF:<source file> line and an
   * end_of_record line.
   *
   * @return a list of each source file path found in the tracefile
   */
  private List<SourceFileCoverage> parse() throws IOException {
    List<SourceFileCoverage> allSourceFiles = new ArrayList<>();
    try (BufferedReader bufferedReader =
        new BufferedReader(new InputStreamReader(inputStream, UTF_8))) {
      String line;
      while ((line = bufferedReader.readLine()) != null) {
        parseLine(line, allSourceFiles);
      }
      bufferedReader.close();
    }
    return allSourceFiles;
  }

  /**
   * Merges {@code currentSourceFileCoverage} into {@code allSourceFilesCoverageData} and resets
   * {@code currentSourceFileCoverage} to null.
   */
  private void reset(List<SourceFileCoverage> allSourceFiles) {
    allSourceFiles.add(currentSourceFileCoverage);
    currentSourceFileCoverage = null;
  }

  /*
   * Reads the line and redirects the parsing to the corresponding {@code parseXLine} method. Every
   * {@code parseXLine} methods fills in data to {@code currentSourceFileCoverage} accordingly.
   */
  private boolean parseLine(String line, List<SourceFileCoverage> allSourceFiles) {
    if (line.startsWith(SF_MARKER)) {
      return parseSFLine(line);
    }
    // currentSourceFileCoverage should be null only before calling an SF line, otherwise
    // the object should have been created in parseSFLine. If currentSourceFileCoverage is null
    // here it means the parser arrived in an invalid state.
    if (currentSourceFileCoverage == null) {
      return false;
    }
    if (line.startsWith(FN_MARKER)) {
      return parseFNLine(line);
    }
    if (line.startsWith(FNDA_MARKER)) {
      return parseFNDALine(line);
    }
    if (line.startsWith(FNF_MARKER)) {
      return parseFNFLine(line);
    }
    if (line.startsWith(FNH_MARKER)) {
      return parseFNHLine(line);
    }
    if (line.startsWith(BRDA_MARKER)) {
      return parseBRDALine(line);
    }
    if (line.startsWith(BA_MARKER)) {
      return parseBALine(line);
    }
    if (line.startsWith(BRF_MARKER)) {
      return parseBRFLine(line);
    }
    if (line.startsWith(BRH_MARKER)) {
      return parseBRHLine(line);
    }
    if (line.startsWith(DA_MARKER)) {
      return parseDALine(line);
    }
    if (line.startsWith(LH_MARKER)) {
      return parseLHLine(line);
    }
    if (line.startsWith(LF_MARKER)) {
      return parseLFLine(line);
    }
    if (line.equals(END_OF_RECORD_MARKER)) {
      reset(allSourceFiles);
      return true;
    }
    logger.log(Level.WARNING, "Tracefile includes invalid line: " + line);
    return false;
  }

  // SF:<path to source file name>
  private boolean parseSFLine(String line) {
    if (currentSourceFileCoverage != null) {
      logger.log(Level.WARNING, "Tracefile doesn't have SF:<source file> line before" + line);
      return false;
    }
    String sourcefile = line.substring(SF_MARKER.length());
    if (sourcefile.isEmpty()) {
      logger.log(Level.WARNING, "Tracefile doesn't contain source file name on line: " + line);
      return false;
    }
    currentSourceFileCoverage = new SourceFileCoverage(sourcefile);
    return true;
  }

  // FN:<line number of function start>,<function name>
  private boolean parseFNLine(String line) {
    String lineContent = line.substring(FN_MARKER.length());
    String[] funcData = lineContent.split(DELIMITER, -1);
    if (funcData.length != 2 || funcData[0].isEmpty() || funcData[1].isEmpty()) {
      logger.log(Level.WARNING, "Tracefile contains invalid FN line " + line);
      return false;
    }
    try {
      int lineNrFunctionStart = Integer.parseInt(funcData[0]);
      String functionName = funcData[1];
      currentSourceFileCoverage.addLineNumber(functionName, lineNrFunctionStart);
    } catch (NumberFormatException e) {
      logger.log(Level.WARNING, "Tracefile contains invalid line number on FN line " + line);
      return false;
    }
    return true;
  }

  // FNDA:<execution count>,<function name>
  private boolean parseFNDALine(String line) {
    String lineContent = line.substring(FNDA_MARKER.length());
    String[] funcData = lineContent.split(DELIMITER, -1);
    if (funcData.length != 2 || funcData[0].isEmpty() || funcData[1].isEmpty()) {
      logger.log(Level.WARNING, "Tracefile contains invalid FNDA line " + line);
      return false;
    }
    try {
      int executionCount = Integer.parseInt(funcData[0]);
      String functionName = funcData[1];
      currentSourceFileCoverage.addFunctionExecution(functionName, executionCount);
    } catch (NumberFormatException e) {
      logger.log(Level.WARNING, "Tracefile contains invalid execution count on FN line " + line);
      return false;
    }
    return true;
  }

  // FNF:<number of functions found>
  private boolean parseFNFLine(String line) {
    String lineContent = line.substring(FNF_MARKER.length());
    if (lineContent.isEmpty()) {
      logger.log(Level.WARNING, "Tracefile contains invalid FNF line " + line);
      return false;
    }
    try {
      int nrFunctionsFound = Integer.parseInt(lineContent);
      assert currentSourceFileCoverage.nrFunctionsFound() == nrFunctionsFound;
    } catch (NumberFormatException e) {
      logger.log(Level.WARNING,
          "Tracefile contains invalid number of functions on FNF line " + line);
      return false;
    }
    return true;
  }

  // FNH:<number of function hit>
  private boolean parseFNHLine(String line) {
    String lineContent = line.substring(FNH_MARKER.length());
    if (lineContent.isEmpty()) {
      logger.log(Level.WARNING, "Tracefile contains invalid FNH line " + line);
      return false;
    }
    try {
      int nrFunctionsHit = Integer.parseInt(lineContent);
      assert currentSourceFileCoverage.nrFunctionsHit() == nrFunctionsHit;
    } catch (NumberFormatException e) {
      logger.log(Level.WARNING,
          "Tracefile contains invalid number of functions hit on FNH line " + line);
      return false;
    }
    return true;
  }

  // BA:<line number>,<taken>
  private boolean parseBALine(String line) {
    String lineContent = line.substring(BA_MARKER.length());
    String[] lineData = lineContent.split(DELIMITER, -1);
    if (lineData.length != 2) {
      logger.log(Level.WARNING, "Tracefile contains invalid BRDA line " + line);
      return false;
    }
    for (String data : lineData) {
      if (data.isEmpty()) {
        logger.log(Level.WARNING, "Tracefile contains invalid BRDA line " + line);
        return false;
      }
    }
    try {
      int lineNumber = Integer.parseInt(lineData[0]);
      int taken = Integer.parseInt(lineData[1]);

      BranchCoverage branchCoverage = BranchCoverage.create(lineNumber, taken);

      currentSourceFileCoverage.addBranch(lineNumber, branchCoverage);
    } catch (NumberFormatException e) {
      logger.log(Level.WARNING, "Tracefile contains an invalid number BA line " + line);
      return false;
    }
    return true;
  }

  // BRDA:<line number>,<block number>,<branch number>,<taken>
  private boolean parseBRDALine(String line) {
    String lineContent = line.substring(BRDA_MARKER.length());
    String[] lineData = lineContent.split(DELIMITER, -1);
    if (lineData.length != 4) {
      logger.log(Level.WARNING, "Tracefile contains invalid BRDA line " + line);
      return false;
    }
    for (String data : lineData) {
      if (data.isEmpty()) {
        logger.log(Level.WARNING, "Tracefile contains invalid BRDA line " + line);
        return false;
      }
    }
    try {
      int lineNumber = Integer.parseInt(lineData[0]);
      String blockNumber = lineData[1];
      String branchNumber = lineData[2];
      String taken = lineData[3];

      boolean wasExecuted = false;
      int executionCount = 0;
      if (taken.equals(TAKEN)) {
        executionCount = Integer.parseInt(taken);
        wasExecuted = true;
      }
      BranchCoverage branchCoverage =
          BranchCoverage.createWithBlockAndBranch(
              lineNumber, blockNumber, branchNumber, executionCount);

      currentSourceFileCoverage.addBranch(lineNumber, branchCoverage);
    } catch (NumberFormatException e) {
      logger.log(Level.WARNING, "Tracefile contains an invalid number BRDA line " + line);
      return false;
    }
    return true;
  }

  // BRF:<number of branches found>
  private boolean parseBRFLine(String line) {
    String lineContent = line.substring(BRF_MARKER.length());
    if (lineContent.isEmpty()) {
      logger.log(Level.WARNING, "Tracefile contains invalid BRF line " + line);
      return false;
    }
    try {
      int nrBranchesFound = Integer.parseInt(lineContent);
      assert currentSourceFileCoverage.nrBranchesFound() == nrBranchesFound;
    } catch (NumberFormatException e) {
      logger.log(Level.WARNING,
          "Tracefile contains invalid number of branches in BRDA line " + line);
      return false;
    }
    return true;
  }

  // BRH:<number of branches hit>
  private boolean parseBRHLine(String line) {
    String lineContent = line.substring(BRH_MARKER.length());
    if (lineContent.isEmpty()) {
      logger.log(Level.WARNING, "Tracefile contains invalid BRH line " + line);
      return false;
    }
    try {
      int nrBranchesHit = Integer.parseInt(lineContent);
      assert currentSourceFileCoverage.nrBranchesHit() == nrBranchesHit;
    } catch (NumberFormatException e) {
      logger.log(Level.WARNING,
          "Tracefile contains invalid number of branches hit in BRH line " + line);
      return false;
    }
    return true;
  }

  // DA:<line number>,<execution count>,[,<checksum>]
  private boolean parseDALine(String line) {
    String lineContent = line.substring(DA_MARKER.length());
    String[] lineData = lineContent.split(DELIMITER, -1);
    if (lineData.length != 2 && lineData.length != 3) {
      logger.log(Level.WARNING, "Tracefile contains invalid DA line " + line);
      return false;
    }
    for (String data : lineData) {
      if (data.isEmpty()) {
        logger.log(Level.WARNING, "Tracefile contains invalid DA line " + line);
        return false;
      }
    }
    try {
      int lineNumber = Integer.parseInt(lineData[0]);
      int executionCount = Integer.parseInt(lineData[1]);
      String checkSum = null;
      if (lineData.length == 3) {
        checkSum = lineData[2];
      }
      LineCoverage lineCoverage =
          LineCoverage.create(lineNumber, executionCount, checkSum);
      currentSourceFileCoverage.addLine(
          lineNumber, lineCoverage);
    } catch (NumberFormatException e) {
      logger.log(Level.WARNING, "Tracefile contains an invalid number on DA line " + line);
      return false;
    }
    return true;
  }

  // LH:<nr of lines with non-zero exec count>
  private boolean parseLHLine(String line) {
    String lineContent = line.substring(LH_MARKER.length());
    if (lineContent.isEmpty()) {
      logger.log(Level.WARNING, "Tracefile contains invalid LHL line " + line);
      return false;
    }
    try {
      int nrLines = Integer.parseInt(lineContent);
      assert currentSourceFileCoverage.nrOfLinesWithNonZeroExecution() == nrLines;
    } catch (NumberFormatException e) {
      logger.log(Level.WARNING, "Tracefile contains an invalid number on LHL line " + line);
      return false;
    }
    return true;
  }

  // LF:<number of instrumented lines>
  private boolean parseLFLine(String line) {
    String lineContent = line.substring(LF_MARKER.length());
    if (lineContent.isEmpty()) {
      logger.log(Level.WARNING, "Tracefile contains invalid LF line " + line);
      return false;
    }
    try {
      int nrLines = Integer.parseInt(lineContent);
      assert currentSourceFileCoverage.nrOfInstrumentedLines() == nrLines;
    } catch (NumberFormatException e) {
      logger.log(Level.WARNING, "Tracefile contains an invalid number on LF line " + line);
      return false;
    }
    return true;
  }
}

