// Copyright (c) 2013 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 "tools/gn/loader.h"

#include "base/bind.h"
#include "base/memory/ptr_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "tools/gn/build_settings.h"
#include "tools/gn/err.h"
#include "tools/gn/filesystem_utils.h"
#include "tools/gn/input_file_manager.h"
#include "tools/gn/parse_tree.h"
#include "tools/gn/scheduler.h"
#include "tools/gn/scope_per_file_provider.h"
#include "tools/gn/settings.h"
#include "tools/gn/source_dir.h"
#include "tools/gn/source_file.h"
#include "tools/gn/trace.h"

namespace {

struct SourceFileAndOrigin {
  SourceFileAndOrigin(const SourceFile& f, const LocationRange& o)
      : file(f),
        origin(o) {
  }

  SourceFile file;
  LocationRange origin;
};

}  // namespace

// Identifies one time a file is loaded in a given toolchain so we don't load
// it more than once.
struct LoaderImpl::LoadID {
  LoadID() {}
  LoadID(const SourceFile& f, const Label& tc_name)
      : file(f),
        toolchain_name(tc_name) {
  }

  bool operator<(const LoadID& other) const {
    if (file.value() == other.file.value())
      return toolchain_name < other.toolchain_name;
    return file < other.file;
  }

  SourceFile file;
  Label toolchain_name;
};

// Our tracking information for a toolchain.
struct LoaderImpl::ToolchainRecord {
  // The default toolchain label can be empty for the first time the default
  // toolchain is loaded, since we don't know it yet. This will be fixed up
  // later. It should be valid in all other cases.
  ToolchainRecord(const BuildSettings* build_settings,
                  const Label& toolchain_label,
                  const Label& default_toolchain_label)
      : settings(build_settings,
                 GetOutputSubdirName(toolchain_label,
                     toolchain_label == default_toolchain_label)),
        is_toolchain_loaded(false),
        is_config_loaded(false) {
    settings.set_default_toolchain_label(default_toolchain_label);
    settings.set_toolchain_label(toolchain_label);
  }

  Settings settings;

  bool is_toolchain_loaded;
  bool is_config_loaded;

  std::vector<SourceFileAndOrigin> waiting_on_me;
};

// -----------------------------------------------------------------------------

const void* const Loader::kDefaultToolchainKey = &kDefaultToolchainKey;

Loader::Loader() {
}

Loader::~Loader() {
}

void Loader::Load(const Label& label, const LocationRange& origin) {
  Load(BuildFileForLabel(label), origin, label.GetToolchainLabel());
}

// static
SourceFile Loader::BuildFileForLabel(const Label& label) {
  return SourceFile(label.dir().value() + "BUILD.gn");
}

// -----------------------------------------------------------------------------

LoaderImpl::LoaderImpl(const BuildSettings* build_settings)
    : pending_loads_(0), build_settings_(build_settings) {
  // There may not be an active TaskRunner at this point. When that's the case,
  // the calling code is expected to call set_task_runner().
  if (base::ThreadTaskRunnerHandle::IsSet())
    task_runner_ = base::ThreadTaskRunnerHandle::Get();
}

LoaderImpl::~LoaderImpl() {
}

void LoaderImpl::Load(const SourceFile& file,
                      const LocationRange& origin,
                      const Label& in_toolchain_name) {
  const Label& toolchain_name = in_toolchain_name.is_null()
      ? default_toolchain_label_ : in_toolchain_name;
  LoadID load_id(file, toolchain_name);
  if (!invocations_.insert(load_id).second)
    return;  // Already in set, so this file was already loaded or schedulerd.

  if (toolchain_records_.empty()) {
    // Nothing loaded, need to load the default build config. The initial load
    // should not specify a toolchain.
    DCHECK(toolchain_name.is_null());

    std::unique_ptr<ToolchainRecord> new_record(
        new ToolchainRecord(build_settings_, Label(), Label()));
    ToolchainRecord* record = new_record.get();
    toolchain_records_[Label()] = std::move(new_record);

    // The default build config is no dependent on the toolchain definition,
    // since we need to load the build config before we know what the default
    // toolchain name is.
    record->is_toolchain_loaded = true;

    record->waiting_on_me.push_back(SourceFileAndOrigin(file, origin));
    ScheduleLoadBuildConfig(&record->settings, Scope::KeyValueMap());

    return;
  }

  ToolchainRecord* record;
  if (toolchain_name.is_null())
    record = toolchain_records_[default_toolchain_label_].get();
  else
    record = toolchain_records_[toolchain_name].get();

  if (!record) {
    DCHECK(!default_toolchain_label_.is_null());

    // No reference to this toolchain found yet, make one.
    std::unique_ptr<ToolchainRecord> new_record(new ToolchainRecord(
        build_settings_, toolchain_name, default_toolchain_label_));
    record = new_record.get();
    toolchain_records_[toolchain_name] = std::move(new_record);

    // Schedule a load of the toolchain using the default one.
    Load(BuildFileForLabel(toolchain_name), origin, default_toolchain_label_);
  }

  if (record->is_config_loaded)
    ScheduleLoadFile(&record->settings, origin, file);
  else
    record->waiting_on_me.push_back(SourceFileAndOrigin(file, origin));
}

void LoaderImpl::ToolchainLoaded(const Toolchain* toolchain) {
  ToolchainRecord* record = toolchain_records_[toolchain->label()].get();
  if (!record) {
    DCHECK(!default_toolchain_label_.is_null());
    std::unique_ptr<ToolchainRecord> new_record(new ToolchainRecord(
        build_settings_, toolchain->label(), default_toolchain_label_));
    record = new_record.get();
    toolchain_records_[toolchain->label()] = std::move(new_record);
  }
  record->is_toolchain_loaded = true;

  // The default build config is loaded first, then its toolchain. Secondary
  // ones are loaded in the opposite order so we can pass toolchain parameters
  // to the build config. So we may or may not have a config at this point.
  if (!record->is_config_loaded) {
    ScheduleLoadBuildConfig(&record->settings, toolchain->args());
  } else {
    // There should be nobody waiting on this if the build config is already
    // loaded.
    DCHECK(record->waiting_on_me.empty());
  }
}

Label LoaderImpl::GetDefaultToolchain() const {
  return default_toolchain_label_;
}

const Settings* LoaderImpl::GetToolchainSettings(const Label& label) const {
  ToolchainRecordMap::const_iterator found_toolchain;
  if (label.is_null()) {
    if (default_toolchain_label_.is_null())
      return nullptr;
    found_toolchain = toolchain_records_.find(default_toolchain_label_);
  } else {
    found_toolchain = toolchain_records_.find(label);
  }

  if (found_toolchain == toolchain_records_.end())
    return nullptr;
  return &found_toolchain->second->settings;
}

void LoaderImpl::ScheduleLoadFile(const Settings* settings,
                                  const LocationRange& origin,
                                  const SourceFile& file) {
  Err err;
  pending_loads_++;
  if (!AsyncLoadFile(origin, settings->build_settings(), file,
                     base::Bind(&LoaderImpl::BackgroundLoadFile, this,
                                settings, file, origin),
                     &err)) {
    g_scheduler->FailWithError(err);
    DecrementPendingLoads();
  }
}

void LoaderImpl::ScheduleLoadBuildConfig(
    Settings* settings,
    const Scope::KeyValueMap& toolchain_overrides) {
  Err err;
  pending_loads_++;
  if (!AsyncLoadFile(LocationRange(), settings->build_settings(),
                     settings->build_settings()->build_config_file(),
                     base::Bind(&LoaderImpl::BackgroundLoadBuildConfig,
                                this, settings, toolchain_overrides),
                     &err)) {
    g_scheduler->FailWithError(err);
    DecrementPendingLoads();
  }
}

void LoaderImpl::BackgroundLoadFile(const Settings* settings,
                                    const SourceFile& file_name,
                                    const LocationRange& origin,
                                    const ParseNode* root) {
  if (!root) {
    task_runner_->PostTask(
        FROM_HERE, base::Bind(&LoaderImpl::DecrementPendingLoads, this));
    return;
  }

  if (g_scheduler->verbose_logging()) {
    g_scheduler->Log("Running", file_name.value() + " with toolchain " +
                     settings->toolchain_label().GetUserVisibleName(false));
  }

  Scope our_scope(settings->base_config());

  const auto location = root->GetRange().begin();
  if (!location.is_null())
    our_scope.AddInputFile(location.file());

  ScopePerFileProvider per_file_provider(&our_scope, true);
  our_scope.set_source_dir(file_name.GetDir());

  // Targets, etc. generated as part of running this file will end up here.
  Scope::ItemVector collected_items;
  our_scope.set_item_collector(&collected_items);

  ScopedTrace trace(TraceItem::TRACE_FILE_EXECUTE, file_name.value());
  trace.SetToolchain(settings->toolchain_label());

  Err err;
  root->Execute(&our_scope, &err);
  if (!err.has_error())
    our_scope.CheckForUnusedVars(&err);

  if (err.has_error()) {
    if (!origin.is_null())
      err.AppendSubErr(Err(origin, "which caused the file to be included."));
    g_scheduler->FailWithError(err);
  }


  // Pass all of the items that were defined off to the builder.
  for (auto& item : collected_items)
    settings->build_settings()->ItemDefined(std::move(item));

  trace.Done();

  task_runner_->PostTask(FROM_HERE, base::Bind(&LoaderImpl::DidLoadFile, this));
}

void LoaderImpl::BackgroundLoadBuildConfig(
    Settings* settings,
    const Scope::KeyValueMap& toolchain_overrides,
    const ParseNode* root) {
  if (!root) {
    task_runner_->PostTask(
        FROM_HERE, base::Bind(&LoaderImpl::DecrementPendingLoads, this));
    return;
  }

  Scope* base_config = settings->base_config();
  base_config->set_source_dir(SourceDir("//"));

  settings->build_settings()->build_args().SetupRootScope(
      base_config, toolchain_overrides);

  base_config->SetProcessingBuildConfig();

  // See kDefaultToolchainKey in the header.
  Label default_toolchain_label;
  if (settings->is_default())
    base_config->SetProperty(kDefaultToolchainKey, &default_toolchain_label);

  ScopedTrace trace(TraceItem::TRACE_FILE_EXECUTE,
      settings->build_settings()->build_config_file().value());
  trace.SetToolchain(settings->toolchain_label());

  Err err;
  root->Execute(base_config, &err);

  // Clear all private variables left in the scope. We want the root build
  // config to be like a .gni file in that variables beginning with an
  // underscore aren't exported.
  base_config->RemovePrivateIdentifiers();

  trace.Done();

  if (err.has_error())
    g_scheduler->FailWithError(err);

  base_config->ClearProcessingBuildConfig();
  if (settings->is_default()) {
    // The default toolchain must have been set in the default build config
    // file.
    if (default_toolchain_label.is_null()) {
      g_scheduler->FailWithError(Err(Location(),
          "The default build config file did not call set_default_toolchain()",
          "If you don't call this, I can't figure out what toolchain to use\n"
          "for all of this code."));
    } else {
      DCHECK(settings->toolchain_label().is_null());
      settings->set_toolchain_label(default_toolchain_label);
    }
  }

  task_runner_->PostTask(FROM_HERE,
                         base::Bind(&LoaderImpl::DidLoadBuildConfig, this,
                                    settings->toolchain_label()));
}

void LoaderImpl::DidLoadFile() {
  DecrementPendingLoads();
}

void LoaderImpl::DidLoadBuildConfig(const Label& label) {
  // Do not return early, we must call DecrementPendingLoads() at the bottom.

  ToolchainRecordMap::iterator found_toolchain = toolchain_records_.find(label);
  ToolchainRecord* record = nullptr;
  if (found_toolchain == toolchain_records_.end()) {
    // When loading the default build config, we'll insert it into the record
    // map with an empty label since we don't yet know what to call it.
    //
    // In this case, we should have exactly one entry in the map with an empty
    // label. We now need to fix up the naming so it refers to the "real" one.
    CHECK_EQ(1U, toolchain_records_.size());
    ToolchainRecordMap::iterator empty_label = toolchain_records_.find(Label());
    CHECK(empty_label != toolchain_records_.end());

    // Fix up the toolchain record.
    std::unique_ptr<ToolchainRecord> moved_record =
        std::move(empty_label->second);
    record = moved_record.get();
    toolchain_records_[label] = std::move(moved_record);
    toolchain_records_.erase(empty_label);

    // Save the default toolchain label.
    default_toolchain_label_ = label;
    DCHECK(record->settings.default_toolchain_label().is_null());
    record->settings.set_default_toolchain_label(label);

    // The settings object should have the toolchain label already set.
    DCHECK(!record->settings.toolchain_label().is_null());

    // Update any stored invocations that refer to the empty toolchain label.
    // This will normally only be one, for the root build file, so brute-force
    // is OK.
    LoadIDSet old_loads;
    invocations_.swap(old_loads);
    for (const auto& load : old_loads) {
      if (load.toolchain_name.is_null()) {
        // Fix up toolchain label
        invocations_.insert(LoadID(load.file, label));
      } else {
        // Can keep the old one.
        invocations_.insert(load);
      }
    }
  } else {
    record = found_toolchain->second.get();
  }

  DCHECK(!record->is_config_loaded);
  DCHECK(record->is_toolchain_loaded);
  record->is_config_loaded = true;

  // Schedule all waiting file loads.
  for (const auto& waiting : record->waiting_on_me)
    ScheduleLoadFile(&record->settings, waiting.origin, waiting.file);
  record->waiting_on_me.clear();

  DecrementPendingLoads();
}

void LoaderImpl::DecrementPendingLoads() {
  DCHECK_GT(pending_loads_, 0);
  pending_loads_--;
  if (pending_loads_ == 0 && !complete_callback_.is_null())
    complete_callback_.Run();
}

bool LoaderImpl::AsyncLoadFile(
    const LocationRange& origin,
    const BuildSettings* build_settings,
    const SourceFile& file_name,
    const base::Callback<void(const ParseNode*)>& callback,
    Err* err) {
  if (async_load_file_.is_null()) {
    return g_scheduler->input_file_manager()->AsyncLoadFile(
        origin, build_settings, file_name, callback, err);
  }
  return async_load_file_.Run(
      origin, build_settings, file_name, callback, err);
}
