/*
 * Copyright (C) 2015, The Android Open Source Project *
 * 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.
 */

#pragma once

#include <set>
#include <string>
#include <vector>

#include <android-base/result.h>

#include "diagnostics.h"

namespace android {
namespace aidl {

using std::set;
using std::string;
using std::vector;

// The oldest SDK version that is supported for each backend. For non-Java backends, these are the
// platform SDK version where the support for the backend was added. For Java backend, this is 1.
// TODO(b/205065703) switch back to DEFAULT_SDK_VERSION_JAVA = 23
constexpr uint32_t DEFAULT_SDK_VERSION_JAVA = 1;
constexpr uint32_t DEFAULT_SDK_VERSION_CPP = 23;
constexpr uint32_t DEFAULT_SDK_VERSION_NDK = 29;
constexpr uint32_t DEFAULT_SDK_VERSION_RUST = 31;

constexpr uint32_t SDK_VERSION_current = 10000;
constexpr uint32_t SDK_VERSION_Tiramisu = 33;

constexpr uint32_t JAVA_PROPAGATE_VERSION = SDK_VERSION_Tiramisu;

// A simple wrapper around ostringstream. This is just to make Options class
// copiable by the implicit copy constructor. If ostingstream is not wrapped,
// the implcit copy constructor is not generated because ostringstream isn't
// copiable. This class makes the field copiable by having a copy constructor
// that does not copy the underlying stream.
class ErrorMessage {
 public:
  ErrorMessage() = default;
  ErrorMessage(const ErrorMessage&) {}
  std::ostringstream stream_;

  template <typename T>
  ErrorMessage& operator<<(T& t) {
    stream_ << t;
    return *this;
  }

  template <typename T>
  ErrorMessage& operator<<(const T& t) {
    stream_ << t;
    return *this;
  }

  // for "<< endl"
  ErrorMessage& operator<<(std::ostream& (*f)(std::ostream&)) {
    f(stream_);
    return *this;
  }
};

// Handles warning-related options (e.g. -W, -w, ...)
class WarningOptions {
 public:
  std::vector<const char*> Parse(int argc, const char* const argv[], ErrorMessage& error_message);
  DiagnosticMapping GetDiagnosticMapping() const;

 private:
  bool as_errors_ = false;           // -Werror
  bool enable_all_ = false;          // -Weverything
  bool disable_all_ = false;         // -w
  std::set<std::string> enabled_;    // -Wfoo
  std::set<std::string> disabled_;   // -Wno-foo
  std::set<std::string> no_errors_;  // -Wno-error=foo
};

class Options final {
 public:
  enum class Language { UNSPECIFIED, JAVA, CPP, NDK, RUST, CPP_ANALYZER };

  enum class Task { HELP, COMPILE, PREPROCESS, DUMP_API, CHECK_API, DUMP_MAPPINGS };

  enum class CheckApiLevel { COMPATIBLE, EQUAL };

  enum class Stability { UNSPECIFIED, VINTF };
  bool StabilityFromString(const std::string& stability, Stability* out_stability);

  Options(int argc, const char* const argv[], Language default_lang = Language::UNSPECIFIED);

  Options PlusImportDir(const std::string& import_dir) const {
    Options copy(*this);
    copy.import_dirs_.insert(import_dir);
    return copy;
  }

  static Options From(const string& cmdline);

  static Options From(const vector<string>& args);

  // Contain no references to unstructured data types (such as a parcelable that is
  // implemented in Java). These interfaces aren't inherently stable but they have the
  // capacity to be stabilized.
  bool IsStructured() const { return structured_; }

  Stability GetStability() const { return stability_; }

  uint32_t GetMinSdkVersion() const { return min_sdk_version_; }

  Language TargetLanguage() const { return language_; }
  bool IsCppOutput() const {
    return language_ == Language::CPP || language_ == Language::NDK ||
           language_ == Language::CPP_ANALYZER;
  }

  Task GetTask() const { return task_; }

  CheckApiLevel GetCheckApiLevel() const { return check_api_level_; }

  const set<string>& ImportDirs() const { return import_dirs_; }

  const vector<string>& PreprocessedFiles() const { return preprocessed_files_; }

  string DependencyFile() const {
    return dependency_file_;
  }

  bool AutoDepFile() const { return auto_dep_file_; }

  bool GenRpc() const { return gen_rpc_; }

  bool GenTraces() const { return gen_traces_; }

  bool GenTransactionNames() const { return gen_transaction_names_; }

  bool DependencyFileNinja() const { return dependency_file_ninja_; }

  const vector<string>& InputFiles() const { return input_files_; }

  // Path to the output file. This is used only when there is only one
  // output file for the invocation. When there are multiple outputs
  // (e.g. compile multiple AIDL files), output files are created under
  // OutputDir().
  const string& OutputFile() const { return output_file_; }

  // Path to the directory where output file(s) will be generated under.
  const string& OutputDir() const { return output_dir_; }

  // Path to the directory where header file(s) will be generated under.
  // Only used when TargetLanguage() == Language::CPP
  const string& OutputHeaderDir() const { return output_header_dir_; }

  bool FailOnParcelable() const { return fail_on_parcelable_; }

  int Version() const { return version_; }

  string Hash() const { return hash_; }

  bool GenLog() const { return gen_log_; }

  bool DumpNoLicense() const { return dump_no_license_; }

  bool Ok() const { return error_message_.stream_.str().empty(); }

  string GetErrorMessage() const { return error_message_.stream_.str(); }

  string GetUsage() const;

  bool GenApiMapping() const { return task_ == Task::DUMP_MAPPINGS; }

  DiagnosticMapping GetDiagnosticMapping() const { return warning_options_.GetDiagnosticMapping(); }

  // The following are for testability, but cannot be influenced on the command line.
  // Threshold of interface methods to enable outlining of onTransact cases.
  size_t onTransact_outline_threshold_{275u};
  // Number of cases to _not_ outline, if outlining is enabled.
  size_t onTransact_non_outline_count_{275u};

 private:
  Options() = default;

  const string myname_;
  Language language_ = Language::UNSPECIFIED;
  Task task_ = Task::COMPILE;
  CheckApiLevel check_api_level_ = CheckApiLevel::COMPATIBLE;
  set<string> import_dirs_;
  vector<string> preprocessed_files_;
  string dependency_file_;
  bool gen_rpc_ = false;
  bool gen_traces_ = false;
  bool gen_transaction_names_ = false;
  bool dependency_file_ninja_ = false;
  bool structured_ = false;
  Stability stability_ = Stability::UNSPECIFIED;
  uint32_t min_sdk_version_ = 0;  // invalid version
  string output_dir_;
  string output_header_dir_;
  bool fail_on_parcelable_ = false;
  bool auto_dep_file_ = false;
  vector<string> input_files_;
  string output_file_;
  int version_ = 0;
  string hash_ = "";
  bool gen_log_ = false;
  bool dump_no_license_ = false;
  ErrorMessage error_message_;
  WarningOptions warning_options_;
};

std::string to_string(Options::Language language);
android::base::Result<uint32_t> MinSdkVersionFromString(const std::string& str);

}  // namespace aidl
}  // namespace android
