// Copyright 2018 The Bazel Authors. 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_RC_FILE_H_
#define BAZEL_SRC_MAIN_CPP_RC_FILE_H_

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

#include "src/main/cpp/sem_ver.h"
#include "src/main/cpp/workspace_layout.h"
#include "absl/container/flat_hash_map.h"
#include "absl/functional/function_ref.h"

namespace blaze {

// Single option in an rc file.
struct RcOption {
  std::string option;
  // Only keep the index of the source file to avoid copying the paths all over.
  // This index points into the RcFile's canonical_source_paths() vector.
  int source_index;
};

// Reads and parses a single rc file with all its imports.
class RcFile {
 public:
  // Constructs a parsed rc file object, or returns a nullptr and sets the
  // error and error text on failure.
  using ReadFileFn =
      absl::FunctionRef<bool(const std::string&, std::string*, std::string*)>;
  using CanonicalizePathFn = absl::FunctionRef<std::string(const std::string&)>;
  enum class ParseError { NONE, UNREADABLE_FILE, INVALID_FORMAT, IMPORT_LOOP };
  static std::unique_ptr<RcFile> Parse(
      const std::string& filename, const WorkspaceLayout* workspace_layout,
      const std::string& workspace, const std::string& build_label,
      const std::optional<SemVer>& sem_ver, ParseError* error,
      std::string* error_text, ReadFileFn read_file = &ReadFileDefault,
      CanonicalizePathFn canonicalize_path = &CanonicalizePathDefault);

  static std::unique_ptr<RcFile> Parse(
      const std::string& filename, const WorkspaceLayout* workspace_layout,
      const std::string& workspace, ParseError* error,
      std::string* error_text, ReadFileFn read_file = &ReadFileDefault,
      CanonicalizePathFn canonicalize_path = &CanonicalizePathDefault);

  // Movable and copyable.
  RcFile(const RcFile&) = default;
  RcFile(RcFile&&) = default;
  RcFile& operator=(const RcFile&) = default;
  RcFile& operator=(RcFile&&) = default;

  // Returns all relevant rc sources for this file (including itself).
  const std::vector<std::string>& canonical_source_paths() const {
    return canonical_rcfile_paths_;
  }

  // Command -> all options for that command (in order of appearance).
  using OptionMap = absl::flat_hash_map<std::string, std::vector<RcOption>>;
  const OptionMap& options() const { return options_; }

 private:
  RcFile() = default;

  // Recursive call to parse a file and its imports.
  ParseError ParseFile(
      const std::string& filename, const std::string& workspace,
      const WorkspaceLayout& workspace_layout, const std::string& build_label,
      const std::optional<SemVer>& sem_ver, ReadFileFn read_file,
      CanonicalizePathFn canonicalize_path,
      std::vector<std::string>& import_stack, std::string* error_text);

  ParseError ParseFile(
      const std::string& filename, const std::string& workspace,
      const WorkspaceLayout& workspace_layout, ReadFileFn read_file,
      CanonicalizePathFn canonicalize_path,
      std::vector<std::string>& import_stack, std::string* error_text);

  static bool ReadFileDefault(const std::string& filename,
                              std::string* contents, std::string* error_msg);
  static std::string CanonicalizePathDefault(const std::string& filename);

  // Full closure of rcfile paths imported from this file (including itself).
  // These are all canonical paths, created with blaze_util::MakeCanonical.
  // This also means all of these paths should exist.
  std::vector<std::string> canonical_rcfile_paths_;
  // All options parsed from the file.
  OptionMap options_;
};

// Checks if the build label passes the given comparison operation and
// condition. An empty return (nullopt) indicates a failure and error_text will
// be filled.
//
// Eg. The following values would evaluate to true since 8.4.5 >= 5.4.0
//  - build_label=8.4.5
//  - op='>='
//  - compare_version=5.4.0
std::optional<bool> BazelVersionMatchesCondition(
    const SemVer& build_label, absl::string_view op,
    const std::string& compare_version, std::string* error_text);

}  // namespace blaze

#endif  // BAZEL_SRC_MAIN_CPP_RC_FILE_H_
