// 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_LOADER_H_
#define TOOLS_GN_LOADER_H_

#include <functional>
#include <map>
#include <memory>
#include <set>

#include "base/memory/ref_counted.h"
#include "tools/gn/label.h"
#include "tools/gn/scope.h"
#include "util/msg_loop.h"

class BuildSettings;
class LocationRange;
class Settings;
class SourceFile;
class Toolchain;

// The loader manages execution of the different build files. It receives
// requests (normally from the Builder) when new references are found, and also
// manages loading the build config files.
//
// This loader class is abstract so it can be mocked out for testing the
// Builder.
class Loader : public base::RefCountedThreadSafe<Loader> {
 public:
  Loader();

  // Loads the given file in the conext of the given toolchain. The initial
  // call to this (the one that actually starts the generation) should have an
  // empty toolchain name, which will trigger the load of the default build
  // config.
  virtual void Load(const SourceFile& file,
                    const LocationRange& origin,
                    const Label& toolchain_name) = 0;

  // Notification that the given toolchain has loaded. This will unblock files
  // waiting on this definition.
  virtual void ToolchainLoaded(const Toolchain* toolchain) = 0;

  // Returns the label of the default toolchain.
  virtual Label GetDefaultToolchain() const = 0;

  // Returns information about the toolchain with the given label. Will return
  // false if we haven't processed this toolchain yet.
  virtual const Settings* GetToolchainSettings(const Label& label) const = 0;

  // Helper function that extracts the file and toolchain name from the given
  // label, and calls Load().
  void Load(const Label& label, const LocationRange& origin);

  // Returns the build file that the given label references.
  static SourceFile BuildFileForLabel(const Label& label);

  // When processing the default build config, we want to capture the argument
  // of set_default_build_config. The implementation of that function uses this
  // constant as a property key to get the Label* out of the scope where the
  // label should be stored.
  static const void* const kDefaultToolchainKey;

 protected:
  friend class base::RefCountedThreadSafe<Loader>;
  virtual ~Loader();
};

class LoaderImpl : public Loader {
 public:
  // Callback to emulate InputFileManager::AsyncLoadFile.
  using AsyncLoadFileCallback =
      std::function<bool(const LocationRange&,
                         const BuildSettings*,
                         const SourceFile&,
                         std::function<void(const ParseNode*)>,
                         Err*)>;

  explicit LoaderImpl(const BuildSettings* build_settings);

  // Loader implementation.
  void Load(const SourceFile& file,
            const LocationRange& origin,
            const Label& toolchain_name) override;
  void ToolchainLoaded(const Toolchain* toolchain) override;
  Label GetDefaultToolchain() const override;
  const Settings* GetToolchainSettings(const Label& label) const override;

  // Sets the task runner corresponding to the main thread. By default this
  // class will use the thread active during construction, but there is not
  // a task runner active during construction all the time.
  void set_task_runner(MsgLoop* task_runner) { task_runner_ = task_runner; }

  // The complete callback is called whenever there are no more pending loads.
  // Called on the main thread only. This may be called more than once if the
  // queue is drained, but then more stuff gets added.
  void set_complete_callback(std::function<void()> cb) {
    complete_callback_ = std::move(cb);
  }

  // This callback is used when the loader finds it wants to load a file.
  void set_async_load_file(AsyncLoadFileCallback cb) {
    async_load_file_ = std::move(cb);
  }

  const Label& default_toolchain_label() const {
    return default_toolchain_label_;
  }

 private:
  struct LoadID;
  struct ToolchainRecord;

  ~LoaderImpl() override;

  // Schedules the input file manager to load the given file.
  void ScheduleLoadFile(const Settings* settings,
                        const LocationRange& origin,
                        const SourceFile& file);
  void ScheduleLoadBuildConfig(Settings* settings,
                               const Scope::KeyValueMap& toolchain_overrides);

  // Runs the given file on the background thread. These are called by the
  // input file manager.
  void BackgroundLoadFile(const Settings* settings,
                          const SourceFile& file_name,
                          const LocationRange& origin,
                          const ParseNode* root);
  void BackgroundLoadBuildConfig(Settings* settings,
                                 const Scope::KeyValueMap& toolchain_overrides,
                                 const ParseNode* root);

  // Posted to the main thread when any file other than a build config file
  // file has completed running.
  void DidLoadFile();

  // Posted to the main thread when any build config file has completed
  // running. The label should be the name of the toolchain.
  //
  // If there is no defauled toolchain loaded yet, we'll assume that the first
  // call to this indicates to the default toolchain, and this function will
  // set the default toolchain name to the given label.
  void DidLoadBuildConfig(const Label& label);

  // Decrements the pending_loads_ variable and issues the complete callback if
  // necessary.
  void DecrementPendingLoads();

  // Forwards to the appropriate location to load the file.
  bool AsyncLoadFile(const LocationRange& origin,
                     const BuildSettings* build_settings,
                     const SourceFile& file_name,
                     std::function<void(const ParseNode*)> callback,
                     Err* err);

  MsgLoop* task_runner_;

  int pending_loads_;
  std::function<void()> complete_callback_;

  // When non-null, use this callback instead of the InputFileManager for
  // mocking purposes.
  AsyncLoadFileCallback async_load_file_;

  using LoadIDSet = std::set<LoadID>;
  LoadIDSet invocations_;

  const BuildSettings* build_settings_;
  Label default_toolchain_label_;

  // Records for the build config file loads.
  using ToolchainRecordMap = std::map<Label, std::unique_ptr<ToolchainRecord>>;
  ToolchainRecordMap toolchain_records_;
};

#endif  // TOOLS_GN_LOADER_H_
