// Copyright 2018 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/lib/clearcut/curl_handle.h"

#include <iostream>
#include <map>
#include <memory>
#include <string>

namespace cobalt::lib::clearcut {

CurlHandle::CurlHandle(CURL *handle) : handle_(handle) {}

CurlHandle::~CurlHandle() {
  if (handle_ != nullptr) {
    curl_easy_cleanup(handle_);
    handle_ = nullptr;
  }
}

StatusOr<std::unique_ptr<CurlHandle>> CurlHandle::Init() {
  CURL *handle_ptr = curl_easy_init();
  if (handle_ptr == nullptr) {
    return Status(util::StatusCode::INTERNAL, "curl_easy_init() returned nullptr");
  }
  std::unique_ptr<CurlHandle> handle(new CurlHandle(handle_ptr));
  CB_RETURN_IF_ERROR(handle->Setopt(CURLOPT_ERRORBUFFER, handle->errbuf_));
  CB_RETURN_IF_ERROR(handle->Setopt(CURLOPT_WRITEDATA, &handle->response_body_));
  CB_RETURN_IF_ERROR(handle->Setopt(CURLOPT_WRITEFUNCTION, CurlHandle::WriteResponseData));
  return handle;
}

size_t CurlHandle::WriteResponseData(char *ptr, size_t size, size_t nmemb, void *userdata) {
  (reinterpret_cast<std::string *>(userdata))->append(reinterpret_cast<char *>(ptr), size * nmemb);
  return size * nmemb;
}

template <class Param>
Status CurlHandle::Setopt(CURLoption option, Param parameter) {
  auto res = curl_easy_setopt(handle_, option, parameter);
  if (res != CURLE_OK) {
    return CURLCodeToStatus(res);
  }
  return Status::OK;
}

Status CurlHandle::SetHeaders(const std::map<std::string, std::string> &headers) {
  if (!headers.empty()) {
    struct curl_slist *header_list = nullptr;
    for (const auto &header : headers) {
      std::string header_str = header.first + ": " + header.second;
      if (header.second.empty()) {
        header_str = header.first + ";";
      }
      header_list = curl_slist_append(header_list, header_str.c_str());
    }
    return Setopt(CURLOPT_HTTPHEADER, header_list);
  }
  return Status::OK;
}

Status CurlHandle::SetTimeout(int64_t timeout_ms) {
  if (timeout_ms > 0) {
    return Setopt(CURLOPT_TIMEOUT_MS, timeout_ms);
  }
  return Status::OK;
}

Status CurlHandle::CURLCodeToStatus(CURLcode code) {
  std::string details;
  if (strlen(errbuf_) != 0) {
    details = errbuf_;
  }
  return Status(util::StatusCode::INTERNAL, curl_easy_strerror(code), details);
}

StatusOr<HTTPResponse> CurlHandle::Post(const std::string &url, std::string body) {
  CB_RETURN_IF_ERROR(Setopt(CURLOPT_URL, url.c_str()));
  CB_RETURN_IF_ERROR(Setopt(CURLOPT_POSTFIELDSIZE, body.size()));
  CB_RETURN_IF_ERROR(Setopt(CURLOPT_POSTFIELDS, body.data()));
  auto result = curl_easy_perform(handle_);

  switch (result) {
    case CURLE_OK:
      int64_t response_code;
      curl_easy_getinfo(handle_, CURLINFO_RESPONSE_CODE, &response_code);
      return HTTPResponse(response_body_, Status::OK, response_code);
    case CURLE_OPERATION_TIMEDOUT:
      return Status(util::StatusCode::DEADLINE_EXCEEDED, "Post request timed out.");
    default:
      return CURLCodeToStatus(result);
  }
}

}  // namespace cobalt::lib::clearcut
