// Copyright 2017 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.

#include "src/tools/singlejar/desugar_checking.h"

#include "src/main/protobuf/desugar_deps.pb.h"
#include "src/tools/singlejar/diag.h"

bool Java8DesugarDepsChecker::Merge(const CDH* cdh, const LH* lh) {
  // Throw away anything previously read, no need to concatenate
  buffer_.reset(new TransientBytes());
  if (Z_NO_COMPRESSION == lh->compression_method()) {
    buffer_->ReadEntryContents(cdh, lh);
  } else if (Z_DEFLATED == lh->compression_method()) {
    if (!inflater_) {
      inflater_.reset(new Inflater());
    }
    buffer_->DecompressEntryContents(cdh, lh, inflater_.get());
  } else {
    diag_errx(2, "META-INF/desugar_deps is neither stored nor deflated");
  }

  // TODO(kmb): Wrap buffer_ as ZeroCopyInputStream to avoid copying out.
  // Note we only copy one file at a time, so overhead should be modest.
  uint32_t checksum;
  const size_t data_size = buffer_->data_size();
  uint8_t* buf = reinterpret_cast<uint8_t*>(malloc(data_size));
  buffer_->CopyOut(reinterpret_cast<uint8_t*>(buf), &checksum);
  buffer_.reset();  // release buffer eagerly

  bazel::tools::desugar::DesugarDepsInfo deps_info;
  google::protobuf::io::CodedInputStream content(buf, data_size);
  if (!deps_info.ParseFromCodedStream(&content)) {
    diag_errx(2, "META-INF/desugar_deps: unable to parse");
  }
  if (!content.ConsumedEntireMessage()) {
    diag_errx(2, "META-INF/desugar_deps: unexpected trailing content");
  }
  free(buf);

  for (const auto& assume_present : deps_info.assume_present()) {
    // This means we need file named <target>.class in the output.  Remember
    // the first origin of this requirement for error messages, drop others.
    needed_deps_.emplace(assume_present.target().binary_name() + ".class",
                         assume_present.origin().binary_name());
  }

  for (const auto& missing : deps_info.missing_interface()) {
    // Remember the first origin of this requirement for error messages, drop
    // subsequent ones.
    missing_interfaces_.emplace(missing.target().binary_name(),
                                missing.origin().binary_name());
  }

  for (const auto& extends : deps_info.interface_with_supertypes()) {
    // Remember interface hierarchy the first time we see this interface, drop
    // subsequent ones for consistency with how singlejar will keep the first
    // occurrence of the file defining the interface.  We'll lazily derive
    // whether missing_interfaces_ inherit default methods with this data later.
    if (extends.extended_interface_size() > 0) {
      std::vector<std::string> extended;
      extended.reserve(extends.extended_interface_size());
      for (const auto& itf : extends.extended_interface()) {
        extended.push_back(itf.binary_name());
      }
      extended_interfaces_.emplace(extends.origin().binary_name(),
                                   std::move(extended));
    }
  }

  for (const auto& companion : deps_info.interface_with_companion()) {
    // Only remember interfaces that definitely have default methods for now.
    // For all other interfaces we'll transitively check extended interfaces
    // in HasDefaultMethods.
    if (companion.num_default_methods() > 0) {
      has_default_methods_[companion.origin().binary_name()] = true;
    }
  }
  return true;
}

void* Java8DesugarDepsChecker::OutputEntry(bool compress) {
  if (verbose_) {
    fprintf(stderr, "Needed deps: %zu\n", needed_deps_.size());
    fprintf(stderr, "Interfaces to check: %zu\n", missing_interfaces_.size());
    fprintf(stderr, "Sub-interfaces: %zu\n", extended_interfaces_.size());
    fprintf(stderr, "Interfaces w/ default methods: %zu\n",
            has_default_methods_.size());
  }
  for (const auto& needed : needed_deps_) {
    if (verbose_) {
      fprintf(stderr, "Looking for %s\n", needed.first.c_str());
    }
    if (!known_member_(needed.first)) {
      if (fail_on_error_) {
        diag_errx(2,
                  "%s referenced by %s but not found.  Is the former defined"
                  " in a neverlink library?",
                  needed.first.c_str(), needed.second.c_str());
      } else {
        error_ = true;
      }
    }
  }

  for (const auto& missing : missing_interfaces_) {
    if (verbose_) {
      fprintf(stderr, "Checking %s\n", missing.first.c_str());
    }
    if (HasDefaultMethods(missing.first)) {
      if (fail_on_error_) {
        diag_errx(
            2,
            "%s needed on the classpath for desugaring %s.  Please add"
            " the missing dependency to the target containing the latter.",
            missing.first.c_str(), missing.second.c_str());
      } else {
        error_ = true;
      }
    }
  }

  // We don't want these files in the output, just check them for consistency
  return nullptr;
}

bool Java8DesugarDepsChecker::HasDefaultMethods(
    const std::string& interface_name) {
  auto cached = has_default_methods_.find(interface_name);
  if (cached != has_default_methods_.end()) {
    return cached->second;
  }

  // Prime with false in case there's a cycle.  We'll update with the true value
  // (ignoring the cycle) below.
  has_default_methods_.emplace(interface_name, false);

  for (const std::string& extended : extended_interfaces_[interface_name]) {
    if (HasDefaultMethods(extended)) {
      has_default_methods_[interface_name] = true;
      return true;
    }
  }
  has_default_methods_[interface_name] = false;
  return false;
}
