// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <lib/cmdline/status.h>
#include <stdio.h>
#include <unistd.h>
#include <zircon/assert.h>

#include <iostream>
#include <memory>
#include <string>
#include <vector>

#include "tools/fidl/fidlc/cmd/fidl-lint/command_line_options.h"
#include "tools/fidl/fidlc/src/findings.h"
#include "tools/fidl/fidlc/src/findings_json.h"
#include "tools/fidl/fidlc/src/lexer.h"
#include "tools/fidl/fidlc/src/linter.h"
#include "tools/fidl/fidlc/src/parser.h"
#include "tools/fidl/fidlc/src/source_manager.h"
#include "tools/fidl/fidlc/src/tree_visitor.h"

namespace {

[[noreturn]] void FailWithUsage(const std::string& argv0, const char* message, ...) {
  va_list args;
  va_start(args, message);
  vfprintf(stderr, message, args);
  va_end(args);
  std::cerr << fidlc::Usage(argv0) << '\n';
  exit(2);  // Exit code 1 is reserved to indicate lint findings
}

[[noreturn]] void Fail(const char* message, ...) {
  va_list args;
  va_start(args, message);
  vfprintf(stderr, message, args);
  va_end(args);
  exit(2);  // Exit code 1 is reserved to indicate lint findings
}

fidlc::Finding DiagnosticToFinding(const fidlc::Diagnostic& diag) {
  const char* check_id = nullptr;
  switch (diag.def.kind) {
    case fidlc::DiagnosticKind::kError:
      check_id = "parse-error";
      break;
    case fidlc::DiagnosticKind::kWarning:
      check_id = "parse-warning";
      break;
    case fidlc::DiagnosticKind::kRetired:
      ZX_PANIC("should never emit a retired diagnostic");
  }
  return fidlc::Finding(diag.span, check_id, diag.Format());
}

void Lint(const fidlc::SourceFile& source_file, fidlc::Findings* findings,
          const std::set<std::string>& included_checks,
          const std::set<std::string>& excluded_checks, bool exclude_by_default,
          std::set<std::string>* excluded_checks_not_found) {
  fidlc::Reporter reporter;
  fidlc::Lexer lexer(source_file, &reporter);
  fidlc::ExperimentalFlagSet experimental_flags;
  fidlc::Parser parser(&lexer, &reporter, experimental_flags);
  std::unique_ptr<fidlc::File> ast = parser.Parse();
  for (auto* diag : reporter.Diagnostics()) {
    findings->push_back(DiagnosticToFinding(*diag));
  }
  if (!parser.Success()) {
    return;
  }

  fidlc::Linter linter;

  linter.set_included_checks(included_checks);
  linter.set_excluded_checks(excluded_checks);
  linter.set_exclude_by_default(exclude_by_default);

  linter.Lint(ast, findings, excluded_checks_not_found);
}

}  // namespace

int main(int argc, char* argv[]) {
  fidlc::CommandLineOptions options;
  std::vector<std::string> filepaths;
  cmdline::Status status =
      fidlc::ParseCommandLine(argc, const_cast<const char**>(argv), &options, &filepaths);
  if (status.has_error()) {
    Fail("%s\n", status.error_message().c_str());
  }

  if (filepaths.empty()) {
    FailWithUsage(argv[0], "No files provided\n");
  }

  fidlc::SourceManager source_manager;

  // Process filenames.
  for (const auto& filepath : filepaths) {
    const char* reason;
    if (!source_manager.CreateSource(filepath, &reason)) {
      Fail("Couldn't read in source data from %s: %s\n", filepath.c_str(), reason);
    }
  }

  std::set<std::string> excluded_checks_not_found;
  if (options.must_find_excluded_checks) {
    // copy excluded checks specified in command line options, and the linter will remove each one
    // encountered during linting.
    excluded_checks_not_found =
        std::set<std::string>(options.excluded_checks.begin(), options.excluded_checks.end());
  }

  bool exclude_by_default = !options.included_checks.empty() && options.excluded_checks.empty();

  // Convert command line vectors to sets, and add internally-disabled checks to excluded
  auto included_checks =
      std::set<std::string>(options.included_checks.begin(), options.included_checks.end());
  auto excluded_checks =
      std::set<std::string>(options.excluded_checks.begin(), options.excluded_checks.end());

  // Add experimental checks to included checks. Experimental checks don't count
  // for enabling exclude_by_default, but do get added added to included_checks
  // to turn them on. Merging included-checks and experimental-checks allows
  // experimental checks to be enabled through either the --include-checks flag
  // or the --experimental-checks flag, which makes it possible to use
  // exclude-by-default mode even if you only want to turn on experimental
  // checks, by passing them through --include-checks rather than
  // --experimental-checks.
  //
  // Note that this works in reverse as well; it is possible to enable a normal
  // check via --experimental-checks, however this has no effect unless the
  // check is also being excluded via --exclude-checks or exclude-by-default in
  // being used because some other check was passed with --include-checks.
  // Allowing non-experimental checks to be enabled via --experimental-checks
  // ensures forward compatibility when a previously-experimental check is
  // officially released an so no-longer experimental.
  included_checks.insert(options.experimental_checks.begin(), options.experimental_checks.end());

  fidlc::Findings findings;
  bool enable_color = !std::getenv("NO_COLOR") && isatty(fileno(stderr));
  for (const auto& source_file : source_manager.sources()) {
    Lint(*source_file, &findings, included_checks, excluded_checks, exclude_by_default,
         &excluded_checks_not_found);
  }

  if (options.format == "text") {
    auto lints = fidlc::FormatFindings(findings, enable_color);
    for (const auto& lint : lints) {
      fprintf(stderr, "%s\n", lint.c_str());
    }
  } else {
    ZX_ASSERT(options.format == "json");  // should never be false
    std::cout << fidlc::FindingsJson(findings).Produce().str();
  }

  if (!excluded_checks_not_found.empty()) {
    std::ostringstream os;
    os << "The following checks were excluded but were never encountered:\n";
    for (auto& check_id : excluded_checks_not_found) {
      os << "  * " << check_id << '\n';
    }
    os << "Please remove these checks from your excluded_checks list and try again.\n";
    Fail(os.str().c_str());
  }

  // Exit with a status of '1' if there were any findings (at least one file was not "lint-free")
  return findings.empty() ? 0 : 1;
}
