// 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/target_manager.h"

#include <deque>

#include "base/bind.h"
#include "base/strings/string_piece.h"
#include "tools/gn/build_settings.h"
#include "tools/gn/err.h"
#include "tools/gn/filesystem_utils.h"
#include "tools/gn/item_node.h"
#include "tools/gn/scheduler.h"
#include "tools/gn/toolchain_manager.h"
#include "tools/gn/value.h"

TargetManager::TargetManager(const BuildSettings* build_settings)
    : build_settings_(build_settings) {
}

TargetManager::~TargetManager() {
}

Target* TargetManager::GetTarget(const Label& label,
                                 const LocationRange& specified_from_here,
                                 Target* dep_from,
                                 Err* err) {
  DCHECK(!label.is_null());
  DCHECK(!label.toolchain_dir().value().empty());
  DCHECK(!label.toolchain_name().empty());

  base::AutoLock lock(build_settings_->item_tree().lock());

  ItemNode* target_node =
      build_settings_->item_tree().GetExistingNodeLocked(label);
  Target* target = NULL;
  if (!target_node) {
    // First time we've seen this, may need to load the file.

    // Compute the settings. The common case is that we have a dep_from and
    // the toolchains match, so we can use the settings from there rather than
    // querying the toolchain manager (which requires locking, etc.).
    const Settings* settings;
    if (dep_from && dep_from->label().ToolchainsEqual(label)) {
      settings = dep_from->settings();
    } else {
      settings =
          build_settings_->toolchain_manager().GetSettingsForToolchainLocked(
              specified_from_here, label.GetToolchainLabel(), err);
      if (!settings)
        return NULL;
    }

    target = new Target(settings, label);
    target_node = new ItemNode(target);
    target_node->set_originally_referenced_from_here(specified_from_here);
    build_settings_->item_tree().AddNodeLocked(target_node);

    // We're generating a node when there is no referencing one.
    if (!dep_from)
      target_node->set_generated_from_here(specified_from_here);

    // Only schedule loading the given target if somebody is depending on it
    // (and we optimize by not re-asking it to run the current file).
    // Otherwise, we're probably generating it right now.
    if (dep_from && dep_from->label().dir() != label.dir()) {
      if (!ScheduleInvocationLocked(specified_from_here, label, err))
        return NULL;
    }
  } else if ((target = target_node->item()->AsTarget())) {
    // Previously saw this item as a target.

    // If we have no dep_from, we're generating it.
    if (!dep_from) {
      // In this case, it had better not already be generated.
      if (target_node->state() != ItemNode::REFERENCED) {
        *err = Err(specified_from_here,
                   "Duplicate target.",
                   "\"" + label.GetUserVisibleName(true) +
                   "\" being defined here.");
        err->AppendSubErr(Err(target_node->generated_from_here(),
                              "Originally defined here."));
        return NULL;
      } else {
        target_node->set_generated_from_here(specified_from_here);
      }
    }
  } else {
    // Error, we previously saw this thing as a non-target.
    *err = Err(specified_from_here, "Not previously a target.",
        "The target being declared here was previously seen referenced as a\n"
        "non-target (like a config)");
    err->AppendSubErr(Err(target_node->originally_referenced_from_here(),
                          "Originally referenced from here."));
    return NULL;
  }

  // Keep a record of the guy asking us for this dependency. We know if
  // somebody is adding a dependency, that guy it himself not resolved.
  if (dep_from && target_node->state() != ItemNode::RESOLVED) {
    build_settings_->item_tree().GetExistingNodeLocked(
        dep_from->label())->AddDependency(target_node);
  }

  return target;
}

void TargetManager::TargetGenerationComplete(const Label& label) {
  base::AutoLock lock(build_settings_->item_tree().lock());
  build_settings_->item_tree().MarkItemGeneratedLocked(label);
}

void TargetManager::GetAllTargets(
    std::vector<const Target*>* all_targets) const {
  base::AutoLock lock(build_settings_->item_tree().lock());

  std::vector<const Item*> all_items;
  build_settings_->item_tree().GetAllItemsLocked(&all_items);
  for (size_t i = 0; i < all_items.size(); i++) {
    const Target* t = all_items[i]->AsTarget();
    if (t)
      all_targets->push_back(t);
  }
}

bool TargetManager::ScheduleInvocationLocked(
    const LocationRange& specified_from_here,
    const Label& label,
    Err* err) {
  return build_settings_->toolchain_manager().ScheduleInvocationLocked(
        specified_from_here, label.GetToolchainLabel(), label.dir(), err);
}
