// Copyright 2014 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef BAZEL_SRC_MAIN_CPP_BLAZE_STARTUP_OPTIONS_H_
#define BAZEL_SRC_MAIN_CPP_BLAZE_STARTUP_OPTIONS_H_

#include <map>
#include <memory>
#include <string>
#include <vector>

#include "src/main/cpp/util/exit_code.h"

namespace blaze {

using std::string;

struct StartupOptions;

// This class holds the parsed startup options for Blaze.
// These options and their defaults must be kept in sync with those
// in java/com/google/devtools/build/lib/blaze/BlazeServerStartupOptions.
// The latter are purely decorative (they affect the help message,
// which displays the defaults).  The actual defaults are defined
// in the constructor.
//
// TODO(bazel-team): The encapsulation is not quite right -- there are some
// places in blaze.cc where some of these fields are explicitly modified. Their
// names also don't conform to the style guide.
class BlazeStartupOptions {
 public:
  enum Architecture { k32Bit, k64Bit };

  BlazeStartupOptions();
  BlazeStartupOptions(const BlazeStartupOptions &rhs);
  ~BlazeStartupOptions();
  BlazeStartupOptions& operator=(const BlazeStartupOptions &rhs);

  // Returns the capitalized name of this binary.
  string GetProductName();

  // Parses a single argument, either from the command line or from the .blazerc
  // "startup" options.
  //
  // rcfile should be an empty string if the option being parsed does not come
  // from a blazerc.
  //
  // Sets "is_space_separated" true if arg is unary and uses the "--foo bar"
  // style, so its value is in next_arg.
  //
  // Sets "is_space_separated" false if arg is either nullary
  // (e.g. "--[no]batch") or is unary but uses the "--foo=bar" style.
  //
  // Returns the exit code after processing the argument. "error" will contain
  // a descriptive string for any return value other than
  // blaze_exit_code::SUCCESS.
  blaze_exit_code::ExitCode ProcessArg(
      const string &arg, const string &next_arg, const string &rcfile,
      bool *is_space_separated, string *error);

  // Adds any other options needed to result.
  void AddExtraOptions(std::vector<string> *result) const;

  // Checks if Blaze needs to be re-executed.  Does not return, if so.
  //
  // Returns the exit code after the check. "error" will contain a descriptive
  // string for any return value other than blaze_exit_code::SUCCESS.
  blaze_exit_code::ExitCode CheckForReExecuteOptions(
      int argc, const char *argv[], string *error);

  // Checks extra fields when processing arg.
  //
  // Returns the exit code after processing the argument. "error" will contain
  // a descriptive string for any return value other than
  // blaze_exit_code::SUCCESS.
  blaze_exit_code::ExitCode ProcessArgExtra(
    const char *arg, const char *next_arg, const string &rcfile,
    const char **value, bool *is_processed, string *error);

  // Return the default path to the JDK used to run Blaze itself
  // (must be an absolute directory).
  string GetDefaultHostJavabase() const;

  Architecture GetBlazeArchitecture() const;

  // Returns the path to the JVM. This should be called after parsing
  // the startup options.
  string GetJvm();

  // Adds JVM tuning flags for Blaze.
  //
  // Returns the exit code after this operation. "error" will be set to a
  // descriptive string for any value other than blaze_exit_code::SUCCESS.
  blaze_exit_code::ExitCode AddJVMArguments(const string &host_javabase,
                                            std::vector<string> *result,
                                            string *error) const;

  // Blaze's output base.  Everything is relative to this.  See
  // the BlazeDirectories Java class for details.
  string output_base;

  // Installation base for a specific release installation.
  string install_base;

  // The toplevel directory containing Blaze's output.  When Blaze is
  // run by a test, we use TEST_TMPDIR, simplifying the correct
  // hermetic invocation of Blaze from tests.
  string output_root;

  // Blaze's output_user_root. Used only for computing install_base and
  // output_base.
  string output_user_root;

  // Block for the Blaze server lock. Otherwise,
  // quit with non-0 exit code if lock can't
  // be acquired immediately.
  bool block_for_lock;

  bool host_jvm_debug;

  string host_jvm_profile;

  string host_jvm_args;

  bool batch;

  // From the man page: "This policy is useful for workloads that are
  // non-interactive, but do not want to lower their nice value, and for
  // workloads that want a deterministic scheduling policy without
  // interactivity causing extra preemptions (between the workload's tasks)."
  bool batch_cpu_scheduling;

  // If negative, don't mess with ionice. Otherwise, set a level from 0-7
  // for best-effort scheduling. 0 is highest priority, 7 is lowest.
  int io_nice_level;

  int max_idle_secs;

  string skyframe;

  bool blaze_cpu;

  // If true, Blaze will listen to OS-level file change notifications.
  bool watchfs;

  // Temporary experimental flag that permits configurable attribute syntax
  // in BUILD files. This will be removed when configurable attributes is
  // a more stable feature.
  bool allow_configurable_attributes;

  // Temporary flag for enabling EventBus exceptions to be fatal.
  bool fatal_event_bus_exceptions;

  // A string to string map specifying where each option comes from. If the
  // value is empty, it was on the command line, if it is a string, it comes
  // from a blazerc file, if a key is not present, it is the default.
  std::map<string, string> option_sources;

  // This can be used for site-specific startup options. For Bazel, this is
  // stubbed
  // out.
  std::unique_ptr<StartupOptions> extra_options;

  // Given the working directory, returns the nearest enclosing directory with a
  // WORKSPACE file in it.  If there is no such enclosing directory, returns "".
  //
  // E.g., if there was a WORKSPACE file in foo/bar/build_root:
  // GetWorkspace('foo/bar') --> ''
  // GetWorkspace('foo/bar/build_root') --> 'foo/bar/build_root'
  // GetWorkspace('foo/bar/build_root/biz') --> 'foo/bar/build_root'
  //
  // The returned path is relative or absolute depending on whether cwd was
  // relative or absolute.
  static string GetWorkspace(const string &cwd);

  // Returns if workspace is a valid build workspace.
  static bool InWorkspace(const string &workspace);

  // Returns the basename for the rc file.
  static string RcBasename();

  // Returns the search paths for the RC file in the workspace.
  static void WorkspaceRcFileSearchPath(std::vector<string>* candidates);

  // Returns the GetHostJavabase. This should be called after parsing
  // the --host_javabase option.
  string GetHostJavabase();

  // Port for web status server, 0 to disable
  int webstatus_port;

 private:
  string host_javabase;

  // Sets default values for members.
  void Init();

  // Copies member variables from rhs to lhs. This cannot use the compiler-
  // generated copy constructor because extra_options is a unique_ptr and
  // unique_ptr deletes its copy constructor.
  void Copy(const BlazeStartupOptions &rhs, BlazeStartupOptions *lhs);

  // Returns the directory to use for storing outputs.
  string GetOutputRoot();
};

}  // namespace blaze
#endif  // BAZEL_SRC_MAIN_CPP_BLAZE_STARTUP_OPTIONS_H_
