// Copyright 2015 The Goma Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "http_init.h"

#include "file_helper.h"
#include "glog/logging.h"
#include "http.h"
#include "ioutil.h"
#include "oauth2.h"
#include "path.h"
#include "util.h"

#define GOMA_DECLARE_FLAGS_ONLY
#include "goma_flags.cc"

using std::string;

namespace devtools_goma {

namespace {

template<typename T>
static bool LoadConfig(const string& filename,
                       bool (*config_parser)(const string&, T*),
                       T* config) {
  string config_string;
  if (!ReadFileToString(filename.c_str(), &config_string)) {
    LOG(WARNING) << "Failed to read " << filename;
    return false;
  }
  if (!config_parser(config_string, config)) {
    LOG(WARNING) << "Failed to parse config in "
                 << filename
                 << " config_string=" << config_string;
    return false;
  }
  return true;
}

static string GetHomeDir() {
#ifndef _WIN32
  static const char *kHomeEnv = "HOME";
#else
  static const char *kHomeEnv = "USERPROFILE";
#endif
  return GetEnv(kHomeEnv);
}

}  // namespace

static void InitOAuth2(HttpClient::Options* http_options) {
    // allow if file doesn't exist, or invalid oauth config.
    // if not found, or invalid oauth config, start with logout state,
    // and user could login on status page (/api/loginz -
    // HandleLoginRequest below).
    if (!LoadConfig(FLAGS_OAUTH2_CONFIG_FILE,
                    ParseOAuth2Config,
                    &http_options->oauth2_config)) {
      DefaultOAuth2Config(&http_options->oauth2_config);
      LOG(INFO) << "Using default OAuth2 config.";
      SaveOAuth2Config(FLAGS_OAUTH2_CONFIG_FILE, http_options->oauth2_config);
    }
    CHECK(http_options->oauth2_config.enabled())
        << "Invalid OAuth2Config in "
        << FLAGS_OAUTH2_CONFIG_FILE;
}

void InitHttpClientOptions(HttpClient::Options* http_options) {
  http_options->proxy_host_name = FLAGS_PROXY_HOST;
  http_options->proxy_port = FLAGS_PROXY_PORT;

  // fields that would be updated by InitFromURL.
  http_options->dest_host_name = FLAGS_STUBBY_PROXY_IP_ADDRESS;
  http_options->dest_port = FLAGS_STUBBY_PROXY_PORT;
  http_options->use_ssl = FLAGS_USE_SSL;
  http_options->url_path_prefix = FLAGS_URL_PATH_PREFIX;

  http_options->extra_params = FLAGS_RPC_EXTRA_PARAMS;
  http_options->fail_fast = FLAGS_FAIL_FAST;

  http_options->reuse_connection = FLAGS_COMPILER_PROXY_REUSE_CONNECTION;

  // Attempt to load and interpret LUCI_CONTEXT. It may define options for an
  // ambient authentication in LUCI environment. We'll decide whether we will
  // use them few lines below. Note that LUCI_CONTEXT environment variable may
  // be defined even if ambient auth is not enabled.
  const string& luci_context_file = GetEnv("LUCI_CONTEXT");
  LuciContextAuth luci_context_auth;
  if (!luci_context_file.empty()) {
    LuciContext luci_context;
    CHECK(LoadConfig(luci_context_file,
                     ParseLuciContext,
                     &luci_context))
        << "LUCI_CONTEXT is set but cannot load it."
        << " filename=" << luci_context_file;
    luci_context_auth = luci_context.local_auth;
    LOG_IF(INFO, !luci_context_auth.enabled())
        << "Running under LUCI, but LUCI_CONTEXT auth is not enabled.";
  }

  // Preference order
  // - GOMA_HTTP_AUTHORIZATION_FILE
  //     - probably debug purpose only, overrides other settings.
  // - GOMA_OAUTH2_CONFIG_FILE
  //    - overrides service account setting for run buildbot locally to test.
  // - GOMA_SERVICE_ACCOUNT_JSON_FILE (maybe used in buildbots)
  // - GOMA_USE_GCE_SERVICE_ACCOUNT (maybe used in buildbots)
  // - LUCI_CONTEXT (ambient in luci environment, if it is enabled)
  // - default goma oauth2 config file
  //
  // Note: having OAuth2 config and LUCI_CONTEXT at once is valid.
  //       (crbug.com/684735#c14).
  if (!FLAGS_HTTP_AUTHORIZATION_FILE.empty()) {
    string auth_header;
    CHECK(ReadFileToString(FLAGS_HTTP_AUTHORIZATION_FILE.c_str(),
                           &auth_header))
        << FLAGS_HTTP_AUTHORIZATION_FILE
        << " : you need http Authorization header in "
        << FLAGS_HTTP_AUTHORIZATION_FILE
        << " or unset GOMA_HTTP_AUTHORIZATION_FILE";
    auth_header = string(StringRstrip(auth_header));
    http_options->authorization = auth_header;

    LOG_IF(WARNING, !FLAGS_OAUTH2_CONFIG_FILE.empty())
        << "GOMA_OAUTH2_CONFIG_FILE is set but ignored. "
        << FLAGS_OAUTH2_CONFIG_FILE;
    LOG_IF(WARNING, !FLAGS_SERVICE_ACCOUNT_JSON_FILE.empty())
        << "GOMA_SERVICE_ACCOUNT_JSON_FILE is set but ignored. "
        << FLAGS_SERVICE_ACCOUNT_JSON_FILE;
    LOG_IF(WARNING, !FLAGS_GCE_SERVICE_ACCOUNT.empty())
        << "GOMA_GCE_SERVICE_ACCOUNT is set but ignored. "
        << FLAGS_GCE_SERVICE_ACCOUNT;
    LOG_IF(WARNING, luci_context_auth.enabled())
        << "LUCI_CONTEXT auth is configured in the environment but ignored.";
  } else if (!FLAGS_OAUTH2_CONFIG_FILE.empty()) {
    InitOAuth2(http_options);

    LOG_IF(WARNING, !FLAGS_SERVICE_ACCOUNT_JSON_FILE.empty())
        << "GOMA_SERVICE_ACCOUNT_JSON_FILE is set but ignored. "
        << FLAGS_SERVICE_ACCOUNT_JSON_FILE;
    LOG_IF(WARNING, !FLAGS_GCE_SERVICE_ACCOUNT.empty())
        << "GOMA_GCE_SERVICE_ACCOUNT is set but ignored. "
        << FLAGS_GCE_SERVICE_ACCOUNT;
    LOG_IF(WARNING, luci_context_auth.enabled())
        << "LUCI_CONTEXT auth is configured in the environment but ignored.";

  } else if (!FLAGS_SERVICE_ACCOUNT_JSON_FILE.empty()) {
    // TODO: fallback if the file doesn't exit?
    http_options->service_account_json_filename =
        FLAGS_SERVICE_ACCOUNT_JSON_FILE;
    LOG_IF(WARNING, !FLAGS_GCE_SERVICE_ACCOUNT.empty())
        << "GOMA_GCE_SERVICE_ACCOUNT is set but ignored. "
        << FLAGS_GCE_SERVICE_ACCOUNT;
    LOG_IF(WARNING, luci_context_auth.enabled())
        << "LUCI_CONTEXT auth is configured in the environment but ignored.";

  } else if (!FLAGS_GCE_SERVICE_ACCOUNT.empty()) {
    http_options->gce_service_account = FLAGS_GCE_SERVICE_ACCOUNT;

    LOG_IF(WARNING, luci_context_auth.enabled())
        << "LUCI_CONTEXT auth is configured in the environment but ignored.";

  } else if (luci_context_auth.enabled()) {
    LOG(INFO) << "Using LUCI ambient authentication"
              << "  default_account_id="
              << luci_context_auth.default_account_id;
    http_options->luci_context_auth = luci_context_auth;

  } else {
    const string homedir = GetHomeDir();
    if (!homedir.empty()) {
      FLAGS_OAUTH2_CONFIG_FILE =
          file::JoinPath(homedir, ".goma_oauth2_config");
      LOG(INFO) << "Use OAUTH2_CONFIG_FILE=" << FLAGS_OAUTH2_CONFIG_FILE;
      InitOAuth2(http_options);
    }
  }
  http_options->capture_response_header =
      FLAGS_HTTP_RPC_CAPTURE_RESPONSE_HEADER;
  http_options->ssl_extra_cert = FLAGS_SSL_EXTRA_CERT;
  http_options->ssl_extra_cert_data = FLAGS_SSL_EXTRA_CERT_DATA;
  http_options->ssl_crl_max_valid_duration = FLAGS_SSL_CRL_MAX_VALID_DURATION;
  http_options->socket_read_timeout_sec =
      atof(FLAGS_HTTP_SOCKET_READ_TIMEOUT_SECS.c_str());
  http_options->min_retry_backoff_ms = FLAGS_HTTP_RPC_MIN_RETRY_BACKOFF;
  http_options->max_retry_backoff_ms = FLAGS_HTTP_RPC_MAX_RETRY_BACKOFF;
}

}  // namespace devtools_goma
