// 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.

#ifndef TOOLS_GN_BUILDER_H_
#define TOOLS_GN_BUILDER_H_

#include <functional>
#include <memory>
#include <unordered_map>

#include "gn/builder_record.h"
#include "gn/builder_record_map.h"
#include "gn/label.h"
#include "gn/label_ptr.h"
#include "gn/unique_vector.h"

class ActionValues;
class Err;
class Loader;
class ParseNode;

// The builder assembles the dependency tree. It is not threadsafe and runs on
// the main thread only. See also BuilderRecord.
class Builder {
 public:
  using ResolvedGeneratedCallback = std::function<void(const BuilderRecord*)>;

  explicit Builder(Loader* loader);
  ~Builder();

  // The resolved callback is called when a target has been both resolved and
  // marked generated. This will be executed only on the main thread.
  void set_resolved_and_generated_callback(
      const ResolvedGeneratedCallback& cb) {
    resolved_and_generated_callback_ = cb;
  }

  Loader* loader() const { return loader_; }

  void ItemDefined(std::unique_ptr<Item> item);

  // Returns NULL if there is not a thing with the corresponding label.
  const Item* GetItem(const Label& label) const;
  const Toolchain* GetToolchain(const Label& label) const;

  std::vector<const BuilderRecord*> GetAllRecords() const;

  // Returns items which should be generated and which are defined.
  std::vector<const Item*> GetAllResolvedItems() const;

  // Returns targets which should be generated and which are defined.
  std::vector<const Target*> GetAllResolvedTargets() const;

  // Returns the record for the given label, or NULL if it doesn't exist.
  // Mostly used for unit tests.
  const BuilderRecord* GetRecord(const Label& label) const;
  BuilderRecord* GetRecord(const Label& label);

  // If there are any undefined references, returns false and sets the error.
  bool CheckForBadItems(Err* err) const;

  // Get or create an empty record for unit-testing.
  BuilderRecord* GetOrCreateRecordForTesting(const Label& label);

 private:
  bool TargetDefined(BuilderRecord* record, Err* err);
  bool ConfigDefined(BuilderRecord* record, Err* err);
  bool ToolchainDefined(BuilderRecord* record, Err* err);

  // Returns the record associated with the given label. This function checks
  // that if we already have references for it, the type matches. If no record
  // exists yet, a new one will be created.
  //
  // If any of the conditions fail, the return value will be null and the error
  // will be set. request_from is used as the source of the error.
  BuilderRecord* GetOrCreateRecordOfType(const Label& label,
                                         const ParseNode* request_from,
                                         BuilderRecord::ItemType type,
                                         Err* err);

  // Returns the record associated with the given label. This function checks
  // that it's already been resolved to the correct type.
  //
  // If any of the conditions fail, the return value will be null and the error
  // will be set. request_from is used as the source of the error.
  BuilderRecord* GetResolvedRecordOfType(const Label& label,
                                         const ParseNode* request_from,
                                         BuilderRecord::ItemType type,
                                         Err* err);

  bool AddDeps(BuilderRecord* record,
               const LabelConfigVector& configs,
               Err* err);
  bool AddDeps(BuilderRecord* record,
               const UniqueVector<LabelConfigPair>& configs,
               Err* err);
  bool AddDeps(BuilderRecord* record,
               const LabelTargetVector& targets,
               Err* err);
  bool AddGenDeps(BuilderRecord* record,
                  const LabelTargetVector& targets,
                  Err* err);
  bool AddPoolDep(BuilderRecord* record, const Target* target, Err* err);
  bool AddToolchainDep(BuilderRecord* record, const Target* target, Err* err);

  // Given a target, sets the "should generate" bit and pushes it through the
  // dependency tree. Any time the bit it set, we ensure that the given item is
  // scheduled to be loaded.
  //
  // If the force flag is set, we'll ignore the current state of the record's
  // should_generate flag, and set it on the dependents every time. This is
  // used when defining a target: the "should generate" may have been set
  // before the item was defined (if it is required by something that is
  // required). In this case, we need to re-push the "should generate" flag
  // to the item's dependencies.
  void RecursiveSetShouldGenerate(BuilderRecord* record, bool force);

  void ScheduleItemLoadIfNecessary(BuilderRecord* record);

  // This takes a BuilderRecord with resolved dependencies, and fills in the
  // target's Label*Vectors with the resolved pointers.
  bool ResolveItem(BuilderRecord* record, Err* err);
  void ScheduleTargetOnResolve(BuilderRecord* record);
  void CompleteAsyncTargetResolution(BuilderRecord* record, const Err& err);
  bool CompleteItemResolution(BuilderRecord* record, Err* err);

  // Fills in the pointers in the given vector based on the labels. We assume
  // that everything should be resolved by this point, so will return an error
  // if anything isn't found or if the type doesn't match.
  bool ResolveDeps(LabelTargetVector* deps, Err* err);
  bool ResolveConfigs(UniqueVector<LabelConfigPair>* configs, Err* err);
  bool ResolvePool(Target* target, Err* err);
  bool ResolveToolchain(Target* target, Err* err);
  bool ResolvePools(Toolchain* toolchain, Err* err);

  // Given a list of unresolved records, tries to find any circular
  // dependencies and returns the string describing the problem. If no circular
  // deps were found, returns the empty string.
  std::string CheckForCircularDependencies(
      const std::vector<const BuilderRecord*>& bad_records) const;

  // Non owning pointer.
  Loader* loader_;

  BuilderRecordMap records_;

  ResolvedGeneratedCallback resolved_and_generated_callback_;

  Builder(const Builder&) = delete;
  Builder& operator=(const Builder&) = delete;
};

#endif  // TOOLS_GN_BUILDER_H_
