// 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 <cstdio>
#include <cstdlib>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <memory>
#include <string>
#include <vector>

#include <unistd.h>
#include <sys/wait.h>

#include "llcpp_codegen.h"
#include "rapidjson/document.h"
#include "rapidjson/error/en.h"
#include "rapidjson/istreamwrapper.h"

namespace fs = std::filesystem;

namespace {

[[noreturn]] void FatalError(const std::string& info) {
  std::cerr << "Error: " << info << ", errno: " << strerror(errno) << std::endl;
  exit(1);
}

rapidjson::Document ReadMetadata(const fs::path& path) {
  rapidjson::Document metadata;
  std::ifstream contents(path);
  if (contents.fail()) {
    FatalError("Failed to read GN metadata at " + std::string(path));
  }
  rapidjson::IStreamWrapper isw(contents);
  rapidjson::ParseResult parse_result = metadata.ParseStream(isw);
  if (!parse_result) {
    FatalError("Failed to parse " + std::string(path) + ", " +
               rapidjson::GetParseError_En(parse_result.Code()) + ", offset " +
               std::to_string(parse_result.Offset()));
  }
  if (!metadata.IsArray()) {
    FatalError("Metadata is not an array");
  }
  return metadata;
}

struct Target {
  fs::path gen_dir;
  std::string name;
  std::vector<fs::path> fidl_sources;
  std::vector<std::string> args;
  fs::path json;
  fs::path header;
  fs::path source;
  fs::path include_base;
};

std::vector<Target> AllTargets(const fs::path& zircon_build_root) {
  std::vector<Target> targets_vector;
  const auto metadata = ReadMetadata(zircon_build_root / "fidl_gen.json");
  for (auto value_it = metadata.Begin();
       value_it != metadata.End(); ++value_it) {
    const auto& target = *value_it;
    const rapidjson::Value& args = target["args"];
    if (!args.IsArray()) {
      FatalError("args in metadata JSON must be an array");
    }
    std::vector<std::string> args_vector;
    for (auto arg_it = args.Begin(); arg_it != args.End(); ++arg_it) {
      args_vector.emplace_back(arg_it->GetString());
    }
    const rapidjson::Value& fidl_sources = target["fidl_sources"];
    if (!fidl_sources.IsArray()) {
      FatalError("fidl_sources in metadata JSON must be an array");
    }
    std::vector<fs::path> fidl_sources_vector;
    for (auto it = fidl_sources.Begin(); it != fidl_sources.End(); ++it) {
      fidl_sources_vector.emplace_back(fs::path(it->GetString()));
    }
    targets_vector.push_back(Target {
      .gen_dir = fs::path(target["target_gen_dir"].GetString()),
      .name = target["name"].GetString(),
      .args = std::move(args_vector),
      .fidl_sources = std::move(fidl_sources_vector),
      .json = fs::path(target["json"].GetString()),
      .header = fs::path(target["header"].GetString()),
      .source = fs::path(target["source"].GetString()),
      .include_base = fs::path(target["include_base"].GetString()),
    });
  }
  return targets_vector;
}

// Run a command with the specified command, working directory, and arguments.
void RunCommand(const std::string& cmd, const std::string& working_directory,
                std::vector<std::string> args) {
  pid_t pid = fork();
  int status;
  switch (pid) {
  case -1:
    FatalError("Failed to fork");
  case 0: {
    status = chdir(working_directory.c_str());
    if (status != 0) {
      FatalError("Failed to chdir to " + working_directory);
    }
    std::vector<char *> c_args;
    c_args.push_back(const_cast<char *>(cmd.c_str()));
    for (const auto& arg : args) {
      c_args.push_back(const_cast<char *>(arg.c_str()));
    }
    c_args.push_back(nullptr);
    execv(cmd.c_str(), &c_args[0]);
    FatalError("when executing " + cmd + ", execv should not return");
  }
  default:
    pid_t ret_pid = waitpid(pid, &status, 0);
    if (pid != ret_pid) {
      FatalError("when executing " + cmd +
                 ", unexpected return value from waitpid: " +
                 std::to_string(ret_pid));
    }
    if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
      FatalError(cmd + " returned an error: " + std::to_string(status));
    }
  }
}

fs::path FindCommonPath(fs::path a, fs::path b) {
  auto a_it = a.begin();
  auto b_it = b.begin();
  fs::path result;
  while (a_it != a.end() && b_it != b.end()) {
    auto& a_part = *a_it;
    auto& b_part = *b_it;
    if (a_part != b_part) {
      break;
    }
    result /= a_part;
    a_it++;
    b_it++;
  }
  return result;
}

bool Diff(fs::path a, fs::path b) {
  std::ifstream a_stream(a.c_str(), std::ios::binary | std::ios::ate);
  std::ifstream b_stream(b.c_str(), std::ios::binary | std::ios::ate);
  if (!a_stream) {
    return false;
  }
  if (!b_stream) {
    return false;
  }
  if (a_stream.tellg() != b_stream.tellg()) {
    return false;
  }
  a_stream.seekg(0, std::ifstream::beg);
  b_stream.seekg(0, std::ifstream::beg);
  return std::equal(std::istreambuf_iterator<char>(a_stream.rdbuf()),
                    std::istreambuf_iterator<char>(),
                    std::istreambuf_iterator<char>(b_stream.rdbuf()));
}

} // namespace

bool DoValidate(std::filesystem::path zircon_build_root,
                std::filesystem::path fidlgen_llcpp_path,
                std::filesystem::path tmp_dir,
                std::vector<fs::path>* out_dependencies) {
  fs::remove_all(tmp_dir);
  fs::create_directories(tmp_dir);
  auto all_targets = AllTargets(zircon_build_root);
  auto normalize = [&zircon_build_root](fs::path path) {
    return fs::weakly_canonical(zircon_build_root / path);
  };
  for (const auto& target : all_targets) {
    for (const auto& source : target.fidl_sources) {
      out_dependencies->push_back(zircon_build_root / source);
    }
    fs::path json = normalize(target.json);
    fs::path header = normalize(target.header);
    fs::path source = normalize(target.source);
    fs::path include_base = normalize(target.include_base);
    fs::path common = FindCommonPath(header,
                                     FindCommonPath(include_base, source));
    // Generate in an alternative location
    fs::path tmp = fs::absolute(tmp_dir) / target.name;
    fs::path alt_header = tmp / fs::relative(header, common);
    fs::path alt_source = tmp / fs::relative(source, common);
    fs::path alt_include_base = tmp / fs::relative(include_base, common);
    std::vector<std::string> args = {
      "-json",
      json,
      "-include-base",
      alt_include_base,
      "-header",
      alt_header,
      "-source",
      alt_source
    };
    RunCommand(fidlgen_llcpp_path, zircon_build_root, args);
    if (!Diff(header, alt_header)) {
      std::cerr << header << " is different from " << alt_header << std::endl;
      return false;
    }
    if (!Diff(source, alt_source)) {
      std::cerr << source << " is different from " << alt_source << std::endl;
      return false;
    }
  }
  return true;
}

void DoUpdate(fs::path zircon_build_root,
              fs::path fidlgen_llcpp_path,
              std::vector<fs::path>* out_dependencies) {
  const auto all_targets = AllTargets(zircon_build_root);
  for (const auto& target : all_targets) {
    for (const auto& source : target.fidl_sources) {
      out_dependencies->push_back(zircon_build_root / source);
    }
    std::cout << "Generating low-level C++ bindings for " << target.name
              << std::endl;
    RunCommand(fidlgen_llcpp_path, zircon_build_root, target.args);
  }
}
