// Copyright 2017 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 <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>

#include <fstream>
#include <iostream>
#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>

#include <fidl/c_generator.h>
#include <fidl/experimental_flags.h>
#include <fidl/flat_ast.h>
#include <fidl/json_generator.h>
#include <fidl/json_schema.h>
#include <fidl/lexer.h>
#include <fidl/library_zx.h>
#include <fidl/names.h>
#include <fidl/parser.h>
#include <fidl/source_manager.h>
#include <fidl/tables_generator.h>

namespace {

void Usage() {
  std::cout
      << "usage: fidlc [--c-header HEADER_PATH]\n"
         "             [--c-client CLIENT_PATH]\n"
         "             [--c-server SERVER_PATH]\n"
         "             [--tables TABLES_PATH]\n"
         "             [--json JSON_PATH]\n"
         "             [--name LIBRARY_NAME]\n"
         "             [--werror]\n"
         "             [--json-schema]\n"
         "             [--files [FIDL_FILE...]...]\n"
         "             [--help]\n"
         "\n"
         " * `--c-header HEADER_PATH`. If present, this flag instructs `fidlc` to output\n"
         "   a C header at the given path.\n"
         "\n"
         " * `--c-client CLIENT_PATH`. If present, this flag instructs `fidlc` to output\n"
         "   the simple C client implementation at the given path.\n"
         "\n"
         " * `--c-server SERVER_PATH`. If present, this flag instructs `fidlc` to output\n"
         "   the simple C server implementation at the given path.\n"
         "\n"
         " * `--tables TABLES_PATH`. If present, this flag instructs `fidlc` to output\n"
         "   coding tables at the given path. The coding tables are required to encode and\n"
         "   decode messages from the C and C++ bindings.\n"
         "\n"
         " * `--json JSON_PATH`. If present, this flag instructs `fidlc` to output the\n"
         "   library's intermediate representation at the given path. The intermediate\n"
         "   representation is JSON that conforms to the schema available via --json-schema.\n"
         "   The intermediate representation is used as input to the various backends.\n"
         "\n"
         " * `--name LIBRARY_NAME`. If present, this flag instructs `fidlc` to validate\n"
         "   that the library being compiled has the given name. This flag is useful to\n"
         "   cross-check between the library's declaration in a build system and the\n"
         "   actual contents of the library.\n"
         "\n"
         " * `--experimental FLAG_NAME`. If present, this flag enables an experimental\n"
         "    feature of fidlc.\n"
         "\n"
         " * `--files [FIDL_FILE...]...`. Each `--file [FIDL_FILE...]` chunk of arguments\n"
         "   describes a library, all of which must share the same top-level library name\n"
         "   declaration. Libraries must be presented in dependency order, with later\n"
         "   libraries able to use declarations from preceding libraries but not vice versa.\n"
         "   Output is only generated for the final library, not for each of its dependencies.\n"
         "\n"
         " * `--json-schema`. If present, this flag instructs `fidlc` to output the\n"
         "   JSON schema of the intermediate representation.\n"
         "\n"
         " * `--werror`. Treats warnings as errors.\n"
         "\n"
         " * `--help`. Prints this help, and exit immediately.\n"
         "\n"
         "All of the arguments can also be provided via a response file, denoted as\n"
         "`@responsefile`. The contents of the file at `responsefile` will be interpreted\n"
         "as a whitespace-delimited list of arguments. Response files cannot be nested,\n"
         "and must be the only argument.\n"
         "\n"
         "See <https://fuchsia.dev/fuchsia-src/development/languages/fidl/reference/compiler>\n"
         "for more information.\n";
  std::cout.flush();
}

void PrintJsonSchema() {
  std::cout << JsonSchema::schema() << "\n";
  std::cout.flush();
}

[[noreturn]] void FailWithUsage(const char* message, ...) {
  va_list args;
  va_start(args, message);
  vfprintf(stderr, message, args);
  va_end(args);
  Usage();
  exit(1);
}

[[noreturn]] void Fail(const char* message, ...) {
  va_list args;
  va_start(args, message);
  vfprintf(stderr, message, args);
  va_end(args);
  exit(1);
}

void MakeParentDirectory(const std::string& filename) {
  std::string::size_type slash = 0;

  for (;;) {
    slash = filename.find('/', slash);
    if (slash == filename.npos) {
      return;
    }

    std::string path = filename.substr(0, slash);
    ++slash;
    if (path.size() == 0u) {
      // Skip creating "/".
      continue;
    }

    if (mkdir(path.data(), 0755) != 0 && errno != EEXIST) {
      Fail("Could not create directory %s for output file %s: error %s\n", path.data(),
           filename.data(), strerror(errno));
    }
  }
}

std::fstream Open(std::string filename, std::ios::openmode mode) {
  if ((mode & std::ios::out) != 0) {
    MakeParentDirectory(filename);
  }

  std::fstream stream;
  stream.open(filename, mode);
  if (!stream.is_open()) {
    Fail("Could not open file: %s\n", filename.data());
  }
  return stream;
}

class Arguments {
 public:
  virtual ~Arguments() {}

  virtual std::string Claim() = 0;
  virtual bool Remaining() const = 0;
};

class ArgvArguments : public Arguments {
 public:
  ArgvArguments(int count, char** arguments)
      : count_(count), arguments_(const_cast<const char**>(arguments)) {}

  std::string Claim() override {
    if (count_ < 1) {
      FailWithUsage("Missing part of an argument\n");
    }
    std::string argument = arguments_[0];
    --count_;
    ++arguments_;
    return argument;
  }

  bool Remaining() const override { return count_ > 0; }

  bool HeadIsResponseFile() {
    if (count_ == 0) {
      return false;
    }
    return arguments_[0][0] == '@';
  }

 private:
  int count_;
  const char** arguments_;
};

class ResponseFileArguments : public Arguments {
 public:
  ResponseFileArguments(std::string_view filename)
      : file_(Open(std::string(filename), std::ios::in)) {
    ConsumeWhitespace();
  }

  std::string Claim() override {
    std::string argument;
    while (Remaining() && !IsWhitespace()) {
      argument.push_back(static_cast<char>(file_.get()));
    }
    ConsumeWhitespace();
    return argument;
  }

  bool Remaining() const override { return !file_.eof(); }

 private:
  bool IsWhitespace() {
    switch (file_.peek()) {
      case ' ':
      case '\n':
      case '\r':
      case '\t':
        return true;
      default:
        return false;
    }
  }

  void ConsumeWhitespace() {
    while (Remaining() && IsWhitespace()) {
      file_.get();
    }
  }

  std::fstream file_;
};

enum struct Behavior {
  kCHeader,
  kCClient,
  kCServer,
  kTables,
  kJSON,
};

bool Parse(const fidl::SourceFile& source_file, fidl::ErrorReporter* error_reporter,
           fidl::flat::Library* library, const fidl::ExperimentalFlags& experimental_flags) {
  fidl::Lexer lexer(source_file, error_reporter);
  fidl::Parser parser(&lexer, error_reporter, experimental_flags);
  auto ast = parser.Parse();
  if (!parser.Ok()) {
    return false;
  }
  if (!library->ConsumeFile(std::move(ast))) {
    return false;
  }
  return true;
}

void Write(std::ostringstream output_stream, const std::string file_path) {
  std::fstream file = Open(file_path, std::ios::out);
  file << output_stream.str();
  file.flush();
  if (file.fail()) {
    Fail("Failed to flush output to file: %s\n", file_path.c_str());
  }
}

}  // namespace

// TODO(pascallouis): remove forward declaration, this was only introduced to
// reduce diff size while breaking things up.
int compile(fidl::ErrorReporter* error_reporter, fidl::flat::Typespace* typespace,
            std::string library_name, std::vector<std::pair<Behavior, std::string>> outputs,
            std::vector<fidl::SourceManager> source_managers,
            fidl::ExperimentalFlags experimental_flags);

int main(int argc, char* argv[]) {
  auto argv_args = std::make_unique<ArgvArguments>(argc, argv);

  // Parse the program name.
  argv_args->Claim();

  if (!argv_args->Remaining()) {
    Usage();
    exit(0);
  }

  // Check for a response file. After this, |args| is either argv or
  // the response file contents.
  Arguments* args = argv_args.get();
  std::unique_ptr<ResponseFileArguments> response_file_args;
  if (argv_args->HeadIsResponseFile()) {
    std::string response = args->Claim();
    if (argv_args->Remaining()) {
      // Response file must be the only argument.
      FailWithUsage("Response files must be the only argument to %s.\n", argv[0]);
    }
    // Drop the leading '@'.
    std::string_view response_file = response.data() + 1;
    response_file_args = std::make_unique<ResponseFileArguments>(response_file);
    args = response_file_args.get();
  }

  std::string library_name;

  bool warnings_as_errors = false;
  std::vector<std::pair<Behavior, std::string>> outputs;
  fidl::ExperimentalFlags experimental_flags;
  while (args->Remaining()) {
    // Try to parse an output type.
    std::string behavior_argument = args->Claim();
    if (behavior_argument == "--help") {
      Usage();
      exit(0);
    } else if (behavior_argument == "--json-schema") {
      PrintJsonSchema();
      exit(0);
    } else if (behavior_argument == "--werror") {
      warnings_as_errors = true;
    } else if (behavior_argument == "--c-header") {
      std::string path = args->Claim();
      outputs.emplace_back(std::make_pair(Behavior::kCHeader, path));
    } else if (behavior_argument == "--c-client") {
      std::string path = args->Claim();
      outputs.emplace_back(std::make_pair(Behavior::kCClient, path));
    } else if (behavior_argument == "--c-server") {
      std::string path = args->Claim();
      outputs.emplace_back(std::make_pair(Behavior::kCServer, path));
    } else if (behavior_argument == "--tables") {
      std::string path = args->Claim();
      outputs.emplace_back(std::make_pair(Behavior::kTables, path));
    } else if (behavior_argument == "--json") {
      std::string path = args->Claim();
      outputs.emplace_back(std::make_pair(Behavior::kJSON, path));
    } else if (behavior_argument == "--name") {
      library_name = args->Claim();
    } else if (behavior_argument == "--experimental") {
      std::string flag = args->Claim();
      if (!experimental_flags.SetFlagByName(flag)) {
        FailWithUsage("Unknown experimental flag %s\n", flag.data());
      }
    } else if (behavior_argument == "--files") {
      // Start parsing filenames.
      break;
    } else {
      FailWithUsage("Unknown argument: %s\n", behavior_argument.data());
    }
  }

  // Prepare source files.
  std::vector<fidl::SourceManager> source_managers;
  source_managers.push_back(fidl::SourceManager());
  std::string library_zx_data = fidl::LibraryZX::kData;
  source_managers.back().AddSourceFile(
      std::make_unique<fidl::SourceFile>(fidl::LibraryZX::kFilename, std::move(library_zx_data)));
  source_managers.push_back(fidl::SourceManager());
  while (args->Remaining()) {
    std::string arg = args->Claim();
    if (arg == "--files") {
      source_managers.emplace_back();
    } else {
      if (!source_managers.back().CreateSource(arg.data())) {
        Fail("Couldn't read in source data from %s\n", arg.data());
      }
    }
  }

  // Ready. Set. Go.
  fidl::ErrorReporter error_reporter(warnings_as_errors);
  auto typespace = fidl::flat::Typespace::RootTypes(&error_reporter);
  auto status = compile(&error_reporter, &typespace, library_name, std::move(outputs),
                        std::move(source_managers), std::move(experimental_flags));
  error_reporter.PrintReports();
  return status;
}

int compile(fidl::ErrorReporter* error_reporter, fidl::flat::Typespace* typespace,
            std::string library_name, std::vector<std::pair<Behavior, std::string>> outputs,
            std::vector<fidl::SourceManager> source_managers,
            fidl::ExperimentalFlags experimental_flags) {
  fidl::flat::Libraries all_libraries;
  const fidl::flat::Library* final_library = nullptr;
  for (const auto& source_manager : source_managers) {
    if (source_manager.sources().empty()) {
      continue;
    }
    auto library = std::make_unique<fidl::flat::Library>(&all_libraries, error_reporter, typespace);
    for (const auto& source_file : source_manager.sources()) {
      if (!Parse(*source_file, error_reporter, library.get(), experimental_flags)) {
        return 1;
      }
    }
    if (!library->Compile()) {
      return 1;
    }
    final_library = library.get();
    auto library_name = fidl::NameLibrary(library->name());
    if (!all_libraries.Insert(std::move(library))) {
      Fail("Multiple libraries with the same name: '%s'\n", library_name.c_str());
    }
  }
  if (!final_library) {
    Fail("No library was produced.\n");
  }
  auto unused_libraries_names = all_libraries.Unused(final_library);
  // Because the sources of library zx are unconditionally included, we filter
  // out this library here. We can remove this logic when zx is used in source
  // like other libraries.
  unused_libraries_names.erase(std::vector<std::string_view>{"zx"});
  if (unused_libraries_names.size() != 0) {
    std::string message = "Unused libraries provided via --files: ";
    bool first = true;
    for (const auto& name : unused_libraries_names) {
      if (first) {
        first = false;
      } else {
        message.append(", ");
      }
      message.append(fidl::NameLibrary(name));
    }
    message.append("\n");
    Fail(message.data());
  }

  // Verify that the produced library's name matches the expected name.
  std::string final_name = fidl::NameLibrary(final_library->name());
  if (!library_name.empty() && final_name != library_name) {
    Fail("Generated library '%s' did not match --name argument: %s\n", final_name.data(),
         library_name.data());
  }

  // We recompile dependencies, and only emit output for the final
  // library.
  for (auto& output : outputs) {
    auto& behavior = output.first;
    auto& file_path = output.second;

    switch (behavior) {
      case Behavior::kCHeader: {
        fidl::CGenerator generator(final_library);
        Write(generator.ProduceHeader(), file_path);
        break;
      }
      case Behavior::kCClient: {
        fidl::CGenerator generator(final_library);
        Write(generator.ProduceClient(), file_path);
        break;
      }
      case Behavior::kCServer: {
        fidl::CGenerator generator(final_library);
        Write(generator.ProduceServer(), file_path);
        break;
      }
      case Behavior::kTables: {
        fidl::TablesGenerator generator(final_library);
        Write(generator.Produce(), file_path);
        break;
      }
      case Behavior::kJSON: {
        fidl::JSONGenerator generator(final_library);
        Write(generator.Produce(), file_path);
        break;
      }
    }
  }
  return 0;
}
