// Copyright 2019 The Fuchsia 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 "src/developer/debug/zxdb/client/curl.h"

#include <map>

#include "src/developer/debug/shared/fd_watcher.h"
#include "src/developer/debug/shared/message_loop.h"
#include "src/lib/fxl/logging.h"

namespace zxdb {
namespace {

class CurlFDWatcher : public debug_ipc::FDWatcher {
 public:
  static CurlFDWatcher instance;
  static std::map<int, debug_ipc::MessageLoop::WatchHandle> watches;
  static bool cleanup_pending;

  void OnFDReady(int fd, bool read, bool write, bool err) override;

 private:
  CurlFDWatcher() = default;
};

bool CurlFDWatcher::cleanup_pending = false;
CurlFDWatcher CurlFDWatcher::instance;
std::map<int, debug_ipc::MessageLoop::WatchHandle> CurlFDWatcher::watches;

void CurlFDWatcher::OnFDReady(int fd, bool read, bool write, bool err) {
  int _ignore;
  int action = 0;

  if (read)
    action |= CURL_CSELECT_IN;
  if (write)
    action |= CURL_CSELECT_OUT;
  if (err)
    action |= CURL_CSELECT_ERR;

  auto result =
      curl_multi_socket_action(Curl::multi_handle, fd, action, &_ignore);
  FXL_DCHECK(result == CURLM_OK);

  if (cleanup_pending) {
    return;
  }

  cleanup_pending = true;
  debug_ipc::MessageLoop::Current()->PostTask(FROM_HERE, []() {
    cleanup_pending = false;

    int _ignore;
    while (auto info = curl_multi_info_read(Curl::multi_handle, &_ignore)) {
      if (info->msg != CURLMSG_DONE) {
        // CURLMSG_DONE is the only value for msg, documented or otherwise,
        // so this is mostly future-proofing at writing.
        continue;
      }

      Curl* curl;
      auto result =
          curl_easy_getinfo(info->easy_handle, CURLINFO_PRIVATE, &curl);
      FXL_DCHECK(result == CURLE_OK);

      auto cb = curl->multi_cb_;
      curl->multi_cb_ = nullptr;
      curl->FreeSList();
      auto rem_result =
          curl_multi_remove_handle(Curl::multi_handle, info->easy_handle);
      FXL_DCHECK(rem_result == CURLM_OK);

      auto ref = curl->self_ref_;
      curl->self_ref_ = nullptr;

      cb(ref.get(), Curl::Error(info->data.result));
    }
  });
}

// Callback given to CURL which it uses to inform us it would like to do IO on
// a socket and that we should add it to our polling in the event loop.
int SocketCallback(CURL* easy, curl_socket_t s, int what, void*, void*) {
  if (what == CURL_POLL_REMOVE || what == CURL_POLL_NONE) {
    CurlFDWatcher::watches.erase(s);
  } else {
    debug_ipc::MessageLoop::WatchMode mode;

    switch (what) {
      case CURL_POLL_IN:
        mode = debug_ipc::MessageLoop::WatchMode::kRead;
        break;
      case CURL_POLL_OUT:
        mode = debug_ipc::MessageLoop::WatchMode::kWrite;
        break;
      case CURL_POLL_INOUT:
        mode = debug_ipc::MessageLoop::WatchMode::kReadWrite;
        break;
      default:
        FXL_NOTREACHED();
        return -1;
    };

    CurlFDWatcher::watches[s] = debug_ipc::MessageLoop::Current()->WatchFD(
        mode, s, &CurlFDWatcher::instance);
  }

  return 0;
}

// Callback given to CURL which it uses to inform us it would like to receive a
// timer notification at a given time in the future.
int TimerCallback(CURLM* multi, long timeout_ms, void*) {
  debug_ipc::MessageLoop::Current()->PostTimer(
      FROM_HERE, timeout_ms, [multi]() {
        int _ignore;
        auto result =
            curl_multi_socket_action(multi, CURL_SOCKET_TIMEOUT, 0, &_ignore);
        FXL_DCHECK(result == CURLM_OK);
      });

  return 0;
}

template <typename T>
void curl_easy_setopt_CHECK(CURL* handle, CURLoption option, T t) {
  auto result = curl_easy_setopt(handle, option, t);
  FXL_DCHECK(result == CURLE_OK);
}

}  // namespace

size_t Curl::global_init = 0;
CURLM* Curl::multi_handle = nullptr;

size_t DoHeaderCallback(char* data, size_t size, size_t nitems, void* curl) {
  Curl* self = reinterpret_cast<Curl*>(curl);
  return self->header_callback_(std::string(data, size * nitems));
}

size_t DoDataCallback(char* data, size_t size, size_t nitems, void* curl) {
  Curl* self = reinterpret_cast<Curl*>(curl);
  return self->data_callback_(std::string(data, size * nitems));
}

Curl::Curl() {
  if (!global_init++) {
    auto res = curl_global_init(CURL_GLOBAL_SSL);
    FXL_DCHECK(!res);
  }

  curl_ = curl_easy_init();
  FXL_DCHECK(curl_);

  // The curl handle has a private pointer which we can stash the address of
  // our wrapper class in. Then anywhere the curl handle appears in the API we
  // can grab our wrapper.
  curl_easy_setopt_CHECK(curl_, CURLOPT_PRIVATE, this);
}

Curl::~Curl() {
  FXL_DCHECK(!multi_cb_);

  if (!curl_) {
    return;
  }

  curl_easy_cleanup(curl_);

  if (!--global_init) {
    if (multi_handle) {
      auto result = curl_multi_cleanup(multi_handle);
      FXL_DCHECK(result == CURLM_OK);
      multi_handle = nullptr;
    }

    curl_global_cleanup();
  }
}

std::shared_ptr<Curl> Curl::MakeShared() {
  auto ret = std::make_shared<Curl>();
  ret->weak_self_ref_ = ret;
  return ret;
}

void Curl::set_post_data(const std::map<std::string, std::string>& items) {
  std::string encoded;

  for (const auto& item : items) {
    if (!encoded.empty()) {
      encoded += "&";
    }

    encoded += Escape(item.first);
    encoded += "=";
    encoded += Escape(item.second);
  }

  set_post_data(std::move(encoded));
}

std::string Curl::Escape(const std::string& input) {
  auto escaped = curl_easy_escape(curl_, input.c_str(), input.size());
  std::string ret(escaped);
  curl_free(escaped);
  return ret;
}

void Curl::PrepareToPerform() {
  FXL_DCHECK(!multi_cb_);

  curl_easy_setopt_CHECK(curl_, CURLOPT_HEADERFUNCTION, DoHeaderCallback);
  curl_easy_setopt_CHECK(curl_, CURLOPT_HEADERDATA, this);
  curl_easy_setopt_CHECK(curl_, CURLOPT_WRITEFUNCTION, DoDataCallback);
  curl_easy_setopt_CHECK(curl_, CURLOPT_WRITEDATA, this);

  // API documentation specifies "A long value of 1" enables this option, so we
  // convert very specifically. Why take chances on sensible behavior?
  curl_easy_setopt_CHECK(curl_, CURLOPT_NOBODY, get_body_ ? 0L : 1L);

  if (post_data_.empty()) {
    curl_easy_setopt_CHECK(curl_, CURLOPT_POST, 0);
  } else {
    curl_easy_setopt_CHECK(curl_, CURLOPT_POSTFIELDS, post_data_.data());
    curl_easy_setopt_CHECK(curl_, CURLOPT_POSTFIELDSIZE, post_data_.size());
  }

  FXL_DCHECK(!slist_);
  for (const auto& header : headers_) {
    slist_ = curl_slist_append(slist_, header.c_str());
  }

  curl_easy_setopt_CHECK(curl_, CURLOPT_HTTPHEADER, slist_);
}

void Curl::FreeSList() {
  if (slist_)
    curl_slist_free_all(slist_);
  slist_ = nullptr;
}

Curl::Error Curl::Perform() {
  PrepareToPerform();
  auto ret = Error(curl_easy_perform(curl_));
  FreeSList();
  return ret;
}

void Curl::Perform(std::function<void(Curl*, Curl::Error)> cb) {
  self_ref_ = weak_self_ref_.lock();
  FXL_DCHECK(self_ref_)
      << "To use async Curl::Perform you must construct with Curl::MakeShared";

  PrepareToPerform();
  InitMulti();
  auto result = curl_multi_add_handle(multi_handle, curl_);
  FXL_DCHECK(result == CURLM_OK);

  multi_cb_ = cb;

  int _ignore;
  result =
      curl_multi_socket_action(multi_handle, CURL_SOCKET_TIMEOUT, 0, &_ignore);
  FXL_DCHECK(result == CURLM_OK);
}

void Curl::InitMulti() {
  if (multi_handle) {
    return;
  }

  multi_handle = curl_multi_init();
  FXL_DCHECK(multi_handle);

  auto result =
      curl_multi_setopt(multi_handle, CURLMOPT_SOCKETFUNCTION, SocketCallback);
  FXL_DCHECK(result == CURLM_OK);
  result =
      curl_multi_setopt(multi_handle, CURLMOPT_TIMERFUNCTION, TimerCallback);
  FXL_DCHECK(result == CURLM_OK);
}

long Curl::ResponseCode() {
  long ret;

  auto result = curl_easy_getinfo(curl_, CURLINFO_RESPONSE_CODE, &ret);
  FXL_DCHECK(result == CURLE_OK);
  return ret;
}

}  // namespace zxdb
