// Copyright 2024 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 <fstream>
#include <iostream>
#include <memory>
#include <ostream>
#include <string>
#include <utility>
#include <vector>

#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/log/die_if_null.h"
#include "absl/strings/str_split.h"
#include "absl/strings/string_view.h"
#include "src/tools/one_version/allowlist.h"
#include "src/tools/one_version/duplicate_class_collector.h"
#include "src/tools/one_version/one_version.h"
#include "src/tools/singlejar/input_jar.h"
#include "src/tools/singlejar/token_stream.h"
#include "src/tools/singlejar/zip_headers.h"

// Scans a classpath and reports one version violations.
//
// usage: --output <file to touch>
//        --inputs <jar1,label1 jar2,label2 ... jarN,labelN>
int main(int argc, char *argv[]) {
  std::string output_file;
  bool succeed_on_found_violations = false;
  std::string allowlist_file;
  std::vector<std::string> inputs;
  ArgTokenStream tokens(argc - 1, argv + 1);
  while (!tokens.AtEnd()) {
    if (tokens.MatchAndSet("--output", &output_file) ||
        tokens.MatchAndSet("--succeed_on_found_violations",
                           &succeed_on_found_violations) ||
        tokens.MatchAndSet("--allowlist", &allowlist_file) ||
        tokens.MatchAndSet("--inputs", &inputs)) {
    } else {
      std::cerr << "error: bad command line argument " << tokens.token()
                << std::endl;
      return 1;
    }
  }

  std::unique_ptr<one_version::Allowlist> allowlist;
  if (allowlist_file.empty()) {
    allowlist = std::make_unique<one_version::MapAllowlist>(
        absl::flat_hash_map<std::string, absl::flat_hash_set<std::string>>());
  } else {
    std::ifstream in(allowlist_file);
    if (!in) {
      std::cerr << "error: unable to open allowlist file: " << allowlist_file
                << std::endl;
      return 1;
    }
    absl::flat_hash_map<std::string, absl::flat_hash_set<std::string>> map;
    std::string line;
    while (std::getline(in, line)) {
      std::vector<std::string> parts =
          absl::StrSplit(line, absl::MaxSplits(' ', 1));
      if (parts.size() != 2) {
        std::cerr << "error: expected <package> <label>, got: " << line
                  << std::endl;
        return 1;
      }
      map[parts[0]].insert(parts[1]);
    }
    allowlist = std::make_unique<one_version::MapAllowlist>(std::move(map));
  }
  // Guess at the number of class files in the input jars in the hope of
  // reducing the need to resize our internal map.
  one_version::OneVersion one_version(std::move(allowlist), inputs.size() * 30);

  for (const std::string &input : inputs) {
    std::vector<std::string> pieces = absl::StrSplit(input, ',');
    if (pieces.size() != 2) {
      std::cerr << "error: expected <jar path>,<label>, got: " << input
                << std::endl;
      return 1;
    }
    std::string jar = pieces[0];
    std::string label = pieces[1];
    InputJar input_jar;
    if (!input_jar.Open(jar)) {
      std::cerr << "error: unable to open: " << jar << std::endl;
      return 1;
    }
    const CDH *dir_entry;
    const LH *local_header;
    while ((dir_entry = input_jar.NextEntry(&local_header))) {
      absl::string_view file_name(ABSL_DIE_IF_NULL(local_header)->file_name(),
                                  local_header->file_name_length());
      one_version.Add(file_name, dir_entry,
                      one_version::Label(label, jar, /*allowlisted=*/false));
    }
    input_jar.Close();
  }

  std::vector<one_version::Violation> violations = one_version.Report();

  // Touch the output file, which exists because blaze actions are required to
  // have outputs but is always empty.
  std::ofstream o(output_file.c_str());
  if (!violations.empty()) {
    // TODO(cushon): support other classpaths (runtime, android resources)
    std::cerr << "Found one definition violations on the runtime classpath:\n"
              << one_version::DuplicateClassCollector::Report(violations);
    return succeed_on_found_violations ? 0 : 1;
  }

  return 0;
}
