// Copyright 2016 The Chromium 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 "gn/ninja_create_bundle_target_writer.h"

#include <iterator>

#include "base/strings/string_util.h"
#include "gn/filesystem_utils.h"
#include "gn/general_tool.h"
#include "gn/ninja_utils.h"
#include "gn/output_file.h"
#include "gn/scheduler.h"
#include "gn/substitution_writer.h"
#include "gn/target.h"
#include "gn/toolchain.h"

namespace {

bool TargetRequireAssetCatalogCompilation(const Target* target) {
  return !target->bundle_data().assets_catalog_sources().empty() ||
         !target->bundle_data().partial_info_plist().is_null();
}

void FailWithMissingToolError(const char* tool_name, const Target* target) {
  g_scheduler->FailWithError(
      Err(nullptr, std::string(tool_name) + " tool not defined",
          "The toolchain " +
              target->toolchain()->label().GetUserVisibleName(false) +
              "\n"
              "used by target " +
              target->label().GetUserVisibleName(false) +
              "\n"
              "doesn't define a \"" +
              tool_name + "\" tool."));
}

bool EnsureAllToolsAvailable(const Target* target) {
  const char* kRequiredTools[] = {
      GeneralTool::kGeneralToolCopyBundleData,
      GeneralTool::kGeneralToolStamp,
  };

  for (size_t i = 0; i < std::size(kRequiredTools); ++i) {
    if (!target->toolchain()->GetTool(kRequiredTools[i])) {
      FailWithMissingToolError(kRequiredTools[i], target);
      return false;
    }
  }

  // The compile_xcassets tool is only required if the target has asset
  // catalog resources to compile.
  if (TargetRequireAssetCatalogCompilation(target)) {
    if (!target->toolchain()->GetTool(
            GeneralTool::kGeneralToolCompileXCAssets)) {
      FailWithMissingToolError(GeneralTool::kGeneralToolCompileXCAssets,
                               target);
      return false;
    }
  }

  return true;
}

}  // namespace

NinjaCreateBundleTargetWriter::NinjaCreateBundleTargetWriter(
    const Target* target,
    std::ostream& out)
    : NinjaTargetWriter(target, out) {}

NinjaCreateBundleTargetWriter::~NinjaCreateBundleTargetWriter() = default;

void NinjaCreateBundleTargetWriter::Run() {
  if (!EnsureAllToolsAvailable(target_))
    return;

  // Stamp users are CopyBundleData, CompileAssetsCatalog, CodeSigning and
  // StampForTarget.
  size_t num_stamp_uses = 4;
  std::vector<OutputFile> order_only_deps = WriteInputDepsStampAndGetDep(
      std::vector<const Target*>(), num_stamp_uses);

  std::string code_signing_rule_name = WriteCodeSigningRuleDefinition();

  std::vector<OutputFile> output_files;
  WriteCopyBundleDataSteps(order_only_deps, &output_files);
  WriteCompileAssetsCatalogStep(order_only_deps, &output_files);
  WriteCodeSigningStep(code_signing_rule_name, order_only_deps, &output_files);

  for (const Target* data_dep : resolved().GetDataDeps(target_))
    order_only_deps.push_back(data_dep->dependency_output_file());
  WriteStampForTarget(output_files, order_only_deps);

  // Write a phony target for the outer bundle directory. This allows other
  // targets to treat the entire bundle as a single unit, even though it is
  // a directory, so that it can be depended upon as a discrete build edge.
  out_ << "build ";

  WriteOutput(
      OutputFile(settings_->build_settings(),
                 target_->bundle_data().GetBundleRootDirOutput(settings_)));

  out_ << ": phony " << target_->dependency_output_file().value();
  out_ << std::endl;
}

std::string NinjaCreateBundleTargetWriter::WriteCodeSigningRuleDefinition() {
  if (target_->bundle_data().code_signing_script().is_null())
    return std::string();

  std::string target_label = target_->label().GetUserVisibleName(true);
  std::string custom_rule_name(target_label);
  base::ReplaceChars(custom_rule_name, ":/()", "_", &custom_rule_name);
  custom_rule_name.append("_code_signing_rule");

  out_ << "rule " << custom_rule_name << std::endl;
  out_ << "  command = ";
  path_output_.WriteFile(out_, settings_->build_settings()->python_path());
  out_ << " ";
  path_output_.WriteFile(out_, target_->bundle_data().code_signing_script());

  const SubstitutionList& args = target_->bundle_data().code_signing_args();
  EscapeOptions args_escape_options;
  args_escape_options.mode = ESCAPE_NINJA_COMMAND;

  for (const auto& arg : args.list()) {
    out_ << " ";
    SubstitutionWriter::WriteWithNinjaVariables(arg, args_escape_options, out_);
  }
  out_ << std::endl;
  out_ << "  description = CODE SIGNING " << target_label << std::endl;
  out_ << "  restat = 1" << std::endl;
  out_ << std::endl;

  return custom_rule_name;
}

void NinjaCreateBundleTargetWriter::WriteCopyBundleDataSteps(
    const std::vector<OutputFile>& order_only_deps,
    std::vector<OutputFile>* output_files) {
  for (const BundleFileRule& file_rule : target_->bundle_data().file_rules())
    WriteCopyBundleFileRuleSteps(file_rule, order_only_deps, output_files);
}

void NinjaCreateBundleTargetWriter::WriteCopyBundleFileRuleSteps(
    const BundleFileRule& file_rule,
    const std::vector<OutputFile>& order_only_deps,
    std::vector<OutputFile>* output_files) {
  // Note that we don't write implicit deps for copy steps. "copy_bundle_data"
  // steps as this is most likely implemented using hardlink in the common case.
  // See NinjaCopyTargetWriter::WriteCopyRules() for a detailed explanation.
  for (const SourceFile& source_file : file_rule.sources()) {
    // There is no need to check for errors here as the substitution will have
    // been performed when computing the list of output of the target during
    // the Target::OnResolved phase earlier.
    OutputFile expanded_output_file;
    file_rule.ApplyPatternToSourceAsOutputFile(
        settings_, target_, target_->bundle_data(), source_file,
        &expanded_output_file,
        /*err=*/nullptr);
    output_files->push_back(expanded_output_file);

    out_ << "build ";
    WriteOutput(std::move(expanded_output_file));
    out_ << ": " << GetNinjaRulePrefixForToolchain(settings_)
         << GeneralTool::kGeneralToolCopyBundleData << " ";
    path_output_.WriteFile(out_, source_file);

    if (!order_only_deps.empty()) {
      out_ << " ||";
      path_output_.WriteFiles(out_, order_only_deps);
    }

    out_ << std::endl;
  }
}

void NinjaCreateBundleTargetWriter::WriteCompileAssetsCatalogStep(
    const std::vector<OutputFile>& order_only_deps,
    std::vector<OutputFile>* output_files) {
  if (!TargetRequireAssetCatalogCompilation(target_))
    return;

  OutputFile compiled_catalog;
  if (!target_->bundle_data().assets_catalog_sources().empty()) {
    compiled_catalog =
        OutputFile(settings_->build_settings(),
                   target_->bundle_data().GetCompiledAssetCatalogPath());
    output_files->push_back(compiled_catalog);
  }

  OutputFile partial_info_plist;
  if (!target_->bundle_data().partial_info_plist().is_null()) {
    partial_info_plist =
        OutputFile(settings_->build_settings(),
                   target_->bundle_data().partial_info_plist());

    output_files->push_back(partial_info_plist);
  }

  // If there are no asset catalog to compile but the "partial_info_plist" is
  // non-empty, then add a target to generate an empty file (to avoid breaking
  // code that depends on this file existence).
  if (target_->bundle_data().assets_catalog_sources().empty()) {
    DCHECK(!target_->bundle_data().partial_info_plist().is_null());

    out_ << "build ";
    WriteOutput(partial_info_plist);
    out_ << ": " << GetNinjaRulePrefixForToolchain(settings_)
         << GeneralTool::kGeneralToolStamp;
    if (!order_only_deps.empty()) {
      out_ << " ||";
      path_output_.WriteFiles(out_, order_only_deps);
    }
    out_ << std::endl;
    return;
  }

  OutputFile input_dep = WriteCompileAssetsCatalogInputDepsStamp(
      target_->bundle_data().assets_catalog_deps());
  DCHECK(!input_dep.value().empty());

  out_ << "build ";
  WriteOutput(std::move(compiled_catalog));
  if (partial_info_plist != OutputFile()) {
    // If "partial_info_plist" is non-empty, then add it to list of implicit
    // outputs of the asset catalog compilation, so that target can use it
    // without getting the ninja error "'foo', needed by 'bar', missing and
    // no known rule to make it".
    out_ << " | ";
    WriteOutput(partial_info_plist);
  }

  out_ << ": " << GetNinjaRulePrefixForToolchain(settings_)
       << GeneralTool::kGeneralToolCompileXCAssets;

  SourceFileSet asset_catalog_bundles;
  for (const auto& source : target_->bundle_data().assets_catalog_sources()) {
    out_ << " ";
    path_output_.WriteFile(out_, source);
    asset_catalog_bundles.insert(source);
  }

  out_ << " | ";
  path_output_.WriteFile(out_, input_dep);

  if (!order_only_deps.empty()) {
    out_ << " ||";
    path_output_.WriteFiles(out_, order_only_deps);
  }

  out_ << std::endl;

  out_ << "  product_type = " << target_->bundle_data().product_type()
       << std::endl;

  if (partial_info_plist != OutputFile()) {
    out_ << "  partial_info_plist = ";
    path_output_.WriteFile(out_, partial_info_plist);
    out_ << std::endl;
  }

  const std::vector<SubstitutionPattern>& flags =
      target_->bundle_data().xcasset_compiler_flags().list();
  if (!flags.empty()) {
    out_ << "  " << SubstitutionXcassetsCompilerFlags.ninja_name << " =";
    EscapeOptions args_escape_options;
    args_escape_options.mode = ESCAPE_NINJA_COMMAND;
    for (const auto& flag : flags) {
      out_ << " ";
      SubstitutionWriter::WriteWithNinjaVariables(flag, args_escape_options,
                                                  out_);
    }
    out_ << std::endl;
  }
}

OutputFile
NinjaCreateBundleTargetWriter::WriteCompileAssetsCatalogInputDepsStamp(
    const std::vector<const Target*>& dependencies) {
  DCHECK(!dependencies.empty());
  if (dependencies.size() == 1)
    return dependencies[0]->dependency_output_file();

  OutputFile xcassets_input_stamp_file =
      GetBuildDirForTargetAsOutputFile(target_, BuildDirType::OBJ);
  xcassets_input_stamp_file.value().append(target_->label().name());
  xcassets_input_stamp_file.value().append(".xcassets.inputdeps.stamp");

  out_ << "build ";
  WriteOutput(xcassets_input_stamp_file);
  out_ << ": " << GetNinjaRulePrefixForToolchain(settings_)
       << GeneralTool::kGeneralToolStamp;

  for (const Target* target : dependencies) {
    out_ << " ";
    path_output_.WriteFile(out_, target->dependency_output_file());
  }
  out_ << std::endl;
  return xcassets_input_stamp_file;
}

void NinjaCreateBundleTargetWriter::WriteCodeSigningStep(
    const std::string& code_signing_rule_name,
    const std::vector<OutputFile>& order_only_deps,
    std::vector<OutputFile>* output_files) {
  if (code_signing_rule_name.empty())
    return;

  OutputFile code_signing_input_stamp_file =
      WriteCodeSigningInputDepsStamp(order_only_deps, output_files);
  DCHECK(!code_signing_input_stamp_file.value().empty());

  out_ << "build";
  std::vector<OutputFile> code_signing_output_files;
  SubstitutionWriter::GetListAsOutputFiles(
      settings_, target_->bundle_data().code_signing_outputs(),
      &code_signing_output_files);
  WriteOutputs(code_signing_output_files);

  // Since the code signature step depends on all the files from the bundle,
  // the create_bundle stamp can just depends on the output of the signature
  // script (dependencies are transitive).
  *output_files = std::move(code_signing_output_files);

  out_ << ": " << code_signing_rule_name;
  out_ << " | ";
  path_output_.WriteFile(out_, code_signing_input_stamp_file);
  out_ << std::endl;
}

OutputFile NinjaCreateBundleTargetWriter::WriteCodeSigningInputDepsStamp(
    const std::vector<OutputFile>& order_only_deps,
    std::vector<OutputFile>* output_files) {
  std::vector<SourceFile> code_signing_input_files;
  code_signing_input_files.push_back(
      target_->bundle_data().code_signing_script());
  code_signing_input_files.insert(
      code_signing_input_files.end(),
      target_->bundle_data().code_signing_sources().begin(),
      target_->bundle_data().code_signing_sources().end());
  for (const OutputFile& output_file : *output_files) {
    code_signing_input_files.push_back(
        output_file.AsSourceFile(settings_->build_settings()));
  }

  DCHECK(!code_signing_input_files.empty());
  if (code_signing_input_files.size() == 1 && order_only_deps.empty())
    return OutputFile(settings_->build_settings(), code_signing_input_files[0]);

  OutputFile code_signing_input_stamp_file =
      GetBuildDirForTargetAsOutputFile(target_, BuildDirType::OBJ);
  code_signing_input_stamp_file.value().append(target_->label().name());
  code_signing_input_stamp_file.value().append(".codesigning.inputdeps.stamp");

  out_ << "build ";
  WriteOutput(code_signing_input_stamp_file);
  out_ << ": " << GetNinjaRulePrefixForToolchain(settings_)
       << GeneralTool::kGeneralToolStamp;

  for (const SourceFile& source : code_signing_input_files) {
    out_ << " ";
    path_output_.WriteFile(out_, source);
  }
  if (!order_only_deps.empty()) {
    out_ << " ||";
    path_output_.WriteFiles(out_, order_only_deps);
  }
  out_ << std::endl;
  return code_signing_input_stamp_file;
}
