// Copyright 2020 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.coverageoutputgenerator;

import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.GZIPInputStream;

/**
 * A {@link Parser} for gcov intermediate json format introduced in GCC 9.1. See the flag {@code
 * --intermediate-format} in <a
 * href="https://gcc.gnu.org/onlinedocs/gcc-9.3.0/gcc/Invoking-Gcov.html">gcov documentation</a>.
 */
public class GcovJsonParser {
  private static final Logger logger = Logger.getLogger(GcovJsonParser.class.getName());
  private final InputStream inputStream;

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

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

  private List<SourceFileCoverage> parse() throws IOException {
    ArrayList<SourceFileCoverage> allSourceFiles = new ArrayList<>();
    try (InputStream gzipStream = new GZIPInputStream(inputStream)) {
      ByteArrayOutputStream contents = new ByteArrayOutputStream();
      byte[] buffer = new byte[1024];
      int length;
      while ((length = gzipStream.read(buffer)) != -1) {
        contents.write(buffer, 0, length);
      }
      Gson gson = new Gson();
      GcovJsonFormat document = gson.fromJson(contents.toString(), GcovJsonFormat.class);
      if (!document.format_version.equals("1")) {
        logger.log(
            Level.WARNING,
            "Expect GCov JSON format version 1, got format version " + document.format_version);
      }
      for (GcovJsonFile file : document.files) {
        SourceFileCoverage currentFileCoverage = new SourceFileCoverage(file.file);
        for (GcovJsonFunction function : file.functions) {
          currentFileCoverage.addLineNumber(function.name, function.start_line);
          currentFileCoverage.addFunctionExecution(function.name, function.execution_count);
        }
        for (GcovJsonLine line : file.lines) {
          currentFileCoverage.addLine(
              line.line_number, LineCoverage.create(line.line_number, line.count, null));
          int branchNumber = 0;
          boolean taken = Arrays.stream(line.branches).anyMatch(b -> b.count > 0);
          for (GcovJsonBranch branch : line.branches) {
            currentFileCoverage.addBranch(
                line.line_number,
                BranchCoverage.createWithBranch(
                    line.line_number, Integer.toString(branchNumber), taken, branch.count));
            branchNumber += 1;
          }
        }
        allSourceFiles.add(currentFileCoverage);
      }
    }

    return allSourceFiles;
  }

  // Classes for the Gson data mapper representing the structure of the GCov JSON format
  // These do not follow the Java naming styleguide as they need to match the JSON field names
  // Documentation can be found in GCov's manpage, of which the source is available at
  // https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=gcc/doc/gcov.texi;h=dcdd7831ff063483d43e5347af0b67083c85ecc4;hb=4212a6a3e44f870412d9025eeb323fd4f50a61da#l184

  static class GcovJsonFormat {
    String gcc_version;
    GcovJsonFile[] files;
    String format_version;
    String current_working_directory;
    String data_file;
  }

  static class GcovJsonFile {
    String file;
    GcovJsonFunction[] functions;
    GcovJsonLine[] lines;
  }

  static class GcovJsonFunction {
    int blocks;
    int end_column;
    int start_line;
    String name;
    int blocks_executed;
    long execution_count;
    String demangled_name;
    int start_column;
    int end_line;
  }

  static class GcovJsonLine {
    GcovJsonBranch[] branches;
    long count;
    int line_number;
    boolean unexecuted_block;
    String function_name;
  }

  static class GcovJsonBranch {
    boolean fallthrough;
    long count;

    @SerializedName("throw")
    boolean _throw;
  }
}
