//
// Copyright (C) 2019 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.

#include "host/libs/web/curl_wrapper.h"

#include <stdio.h>

#include <fstream>
#include <mutex>
#include <sstream>
#include <string>
#include <thread>

#include <android-base/logging.h>
#include <curl/curl.h>
#include <json/json.h>

namespace cuttlefish {
namespace {

size_t curl_to_function_cb(char* ptr, size_t, size_t nmemb, void* userdata) {
  CurlWrapper::DataCallback* callback = (CurlWrapper::DataCallback*)userdata;
  if (!(*callback)(ptr, nmemb)) {
    return 0;  // Signals error to curl
  }
  return nmemb;
}

size_t file_write_callback(char *ptr, size_t, size_t nmemb, void *userdata) {
  std::stringstream* stream = (std::stringstream*) userdata;
  stream->write(ptr, nmemb);
  return nmemb;
}

curl_slist* build_slist(const std::vector<std::string>& strings) {
  curl_slist* curl_headers = nullptr;
  for (const auto& str : strings) {
    curl_slist* temp = curl_slist_append(curl_headers, str.c_str());
    if (temp == nullptr) {
      LOG(ERROR) << "curl_slist_append failed to add " << str;
      if (curl_headers) {
        curl_slist_free_all(curl_headers);
        return nullptr;
      }
    }
    curl_headers = temp;
  }
  return curl_headers;
}

class CurlWrapperImpl : public CurlWrapper {
 public:
  CurlWrapperImpl() {
    curl_ = curl_easy_init();
    if (!curl_) {
      LOG(ERROR) << "failed to initialize curl";
      return;
    }
  }
  ~CurlWrapperImpl() { curl_easy_cleanup(curl_); }

  CurlResponse<std::string> PostToString(
      const std::string& url, const std::string& data_to_write,
      const std::vector<std::string>& headers) override {
    std::lock_guard<std::mutex> lock(mutex_);
    LOG(INFO) << "Attempting to download \"" << url << "\"";
    if (!curl_) {
      LOG(ERROR) << "curl was not initialized\n";
      return {"", -1};
    }
    curl_slist* curl_headers = build_slist(headers);
    curl_easy_reset(curl_);
    curl_easy_setopt(curl_, CURLOPT_CAINFO,
                     "/etc/ssl/certs/ca-certificates.crt");
    curl_easy_setopt(curl_, CURLOPT_HTTPHEADER, curl_headers);
    curl_easy_setopt(curl_, CURLOPT_URL, url.c_str());
    curl_easy_setopt(curl_, CURLOPT_POSTFIELDSIZE, data_to_write.size());
    curl_easy_setopt(curl_, CURLOPT_POSTFIELDS, data_to_write.c_str());
    std::stringstream data_to_read;
    curl_easy_setopt(curl_, CURLOPT_WRITEFUNCTION, file_write_callback);
    curl_easy_setopt(curl_, CURLOPT_WRITEDATA, &data_to_read);
    char error_buf[CURL_ERROR_SIZE];
    curl_easy_setopt(curl_, CURLOPT_ERRORBUFFER, error_buf);
    curl_easy_setopt(curl_, CURLOPT_VERBOSE, 1L);
    CURLcode res = curl_easy_perform(curl_);
    if (curl_headers) {
      curl_slist_free_all(curl_headers);
    }
    if (res != CURLE_OK) {
      LOG(ERROR) << "curl_easy_perform() failed. "
                 << "Code was \"" << res << "\". "
                 << "Strerror was \"" << curl_easy_strerror(res) << "\". "
                 << "Error buffer was \"" << error_buf << "\".";
      return {"", -1};
    }
    long http_code = 0;
    curl_easy_getinfo(curl_, CURLINFO_RESPONSE_CODE, &http_code);
    return {data_to_read.str(), http_code};
  }

  CurlResponse<Json::Value> PostToJson(
      const std::string& url, const std::string& data_to_write,
      const std::vector<std::string>& headers) override {
    CurlResponse<std::string> response =
        PostToString(url, data_to_write, headers);
    const std::string& contents = response.data;
    Json::CharReaderBuilder builder;
    std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
    Json::Value json;
    std::string errorMessage;
    if (!reader->parse(&*contents.begin(), &*contents.end(), &json,
                       &errorMessage)) {
      LOG(ERROR) << "Could not parse json: " << errorMessage;
      json["error"] = "Failed to parse json.";
      json["response"] = contents;
    }
    return {json, response.http_code};
  }

  CurlResponse<Json::Value> PostToJson(
      const std::string& url, const Json::Value& data_to_write,
      const std::vector<std::string>& headers) override {
    std::stringstream json_str;
    json_str << data_to_write;
    return PostToJson(url, json_str.str(), headers);
  }

  CurlResponse<bool> DownloadToCallback(
      DataCallback callback, const std::string& url,
      const std::vector<std::string>& headers) {
    std::lock_guard<std::mutex> lock(mutex_);
    LOG(INFO) << "Attempting to download \"" << url << "\"";
    if (!curl_) {
      LOG(ERROR) << "curl was not initialized\n";
      return {false, -1};
    }
    if (!callback(nullptr, 0)) {  // Signal start of data
      LOG(ERROR) << "Callback failure\n";
      return {false, -1};
    }
    curl_slist* curl_headers = build_slist(headers);
    curl_easy_reset(curl_);
    curl_easy_setopt(curl_, CURLOPT_CAINFO,
                     "/etc/ssl/certs/ca-certificates.crt");
    curl_easy_setopt(curl_, CURLOPT_HTTPHEADER, curl_headers);
    curl_easy_setopt(curl_, CURLOPT_URL, url.c_str());
    curl_easy_setopt(curl_, CURLOPT_WRITEFUNCTION, curl_to_function_cb);
    curl_easy_setopt(curl_, CURLOPT_WRITEDATA, &callback);
    char error_buf[CURL_ERROR_SIZE];
    curl_easy_setopt(curl_, CURLOPT_ERRORBUFFER, error_buf);
    curl_easy_setopt(curl_, CURLOPT_VERBOSE, 1L);
    CURLcode res = curl_easy_perform(curl_);
    if (curl_headers) {
      curl_slist_free_all(curl_headers);
    }
    if (res != CURLE_OK) {
      LOG(ERROR) << "curl_easy_perform() failed. "
                 << "Code was \"" << res << "\". "
                 << "Strerror was \"" << curl_easy_strerror(res) << "\". "
                 << "Error buffer was \"" << error_buf << "\".";
      return {false, -1};
    }
    long http_code = 0;
    curl_easy_getinfo(curl_, CURLINFO_RESPONSE_CODE, &http_code);
    return {true, http_code};
  }

  CurlResponse<std::string> DownloadToFile(
      const std::string& url, const std::string& path,
      const std::vector<std::string>& headers) {
    LOG(INFO) << "Attempting to save \"" << url << "\" to \"" << path << "\"";
    std::fstream stream;
    auto callback = [&stream, path](char* data, size_t size) -> bool {
      if (data == nullptr) {
        stream.open(path, std::ios::out | std::ios::binary | std::ios::trunc);
        return !stream.fail();
      }
      stream.write(data, size);
      return !stream.fail();
    };
    auto callback_res = DownloadToCallback(callback, url, headers);
    if (!callback_res.data) {
      return {"", callback_res.http_code};
    }
    return {path, callback_res.http_code};
    std::lock_guard<std::mutex> lock(mutex_);
    if (!curl_) {
      LOG(ERROR) << "curl was not initialized\n";
      return {"", -1};
    }
  }

  CurlResponse<std::string> DownloadToString(
      const std::string& url, const std::vector<std::string>& headers) {
    std::stringstream stream;
    auto callback = [&stream](char* data, size_t size) -> bool {
      if (data == nullptr) {
        stream = std::stringstream();
        return true;
      }
      stream.write(data, size);
      return true;
    };
    auto callback_res = DownloadToCallback(callback, url, headers);
    if (!callback_res.data) {
      return {"", callback_res.http_code};
    }
    return {stream.str(), callback_res.http_code};
  }

  CurlResponse<Json::Value> DownloadToJson(
      const std::string& url, const std::vector<std::string>& headers) {
    CurlResponse<std::string> response = DownloadToString(url, headers);
    const std::string& contents = response.data;
    Json::CharReaderBuilder builder;
    std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
    Json::Value json;
    std::string errorMessage;
    if (!reader->parse(&*contents.begin(), &*contents.end(), &json,
                       &errorMessage)) {
      LOG(ERROR) << "Could not parse json: " << errorMessage;
      json["error"] = "Failed to parse json.";
      json["response"] = contents;
    }
    return {json, response.http_code};
  }

  CurlResponse<Json::Value> DeleteToJson(
      const std::string& url,
      const std::vector<std::string>& headers) override {
    std::lock_guard<std::mutex> lock(mutex_);
    LOG(INFO) << "Attempting to download \"" << url << "\"";
    if (!curl_) {
      LOG(ERROR) << "curl was not initialized\n";
      return {"", -1};
    }
    curl_slist* curl_headers = build_slist(headers);
    curl_easy_reset(curl_);
    curl_easy_setopt(curl_, CURLOPT_CUSTOMREQUEST, "DELETE");
    curl_easy_setopt(curl_, CURLOPT_CAINFO,
                     "/etc/ssl/certs/ca-certificates.crt");
    curl_easy_setopt(curl_, CURLOPT_HTTPHEADER, curl_headers);
    curl_easy_setopt(curl_, CURLOPT_URL, url.c_str());
    std::stringstream data_to_read;
    curl_easy_setopt(curl_, CURLOPT_WRITEFUNCTION, file_write_callback);
    curl_easy_setopt(curl_, CURLOPT_WRITEDATA, &data_to_read);
    char error_buf[CURL_ERROR_SIZE];
    curl_easy_setopt(curl_, CURLOPT_ERRORBUFFER, error_buf);
    curl_easy_setopt(curl_, CURLOPT_VERBOSE, 1L);
    CURLcode res = curl_easy_perform(curl_);
    if (curl_headers) {
      curl_slist_free_all(curl_headers);
    }
    if (res != CURLE_OK) {
      LOG(ERROR) << "curl_easy_perform() failed. "
                 << "Code was \"" << res << "\". "
                 << "Strerror was \"" << curl_easy_strerror(res) << "\". "
                 << "Error buffer was \"" << error_buf << "\".";
      return {"", -1};
    }
    long http_code = 0;
    curl_easy_getinfo(curl_, CURLINFO_RESPONSE_CODE, &http_code);

    auto contents = data_to_read.str();
    Json::CharReaderBuilder builder;
    std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
    Json::Value json;
    std::string errorMessage;
    if (!reader->parse(&*contents.begin(), &*contents.end(), &json,
                       &errorMessage)) {
      LOG(ERROR) << "Could not parse json: " << errorMessage;
      json["error"] = "Failed to parse json.";
      json["response"] = contents;
    }
    return {json, http_code};
  }

  std::string UrlEscape(const std::string& text) override {
    char* escaped_str = curl_easy_escape(curl_, text.c_str(), text.size());
    std::string ret{escaped_str};
    curl_free(escaped_str);
    return ret;
  }

 private:
  CURL* curl_;
  std::mutex mutex_;
};

class CurlServerErrorRetryingWrapper : public CurlWrapper {
 public:
  CurlServerErrorRetryingWrapper(CurlWrapper& inner, int retry_attempts,
                                 std::chrono::milliseconds retry_delay)
      : inner_curl_(inner),
        retry_attempts_(retry_attempts),
        retry_delay_(retry_delay) {}

  CurlResponse<std::string> PostToString(
      const std::string& url, const std::string& data,
      const std::vector<std::string>& headers) override {
    return RetryImpl<std::string>(
        [&, this]() { return inner_curl_.PostToString(url, data, headers); });
  }

  CurlResponse<Json::Value> PostToJson(
      const std::string& url, const Json::Value& data,
      const std::vector<std::string>& headers) override {
    return RetryImpl<Json::Value>(
        [&, this]() { return inner_curl_.PostToJson(url, data, headers); });
  }

  CurlResponse<Json::Value> PostToJson(
      const std::string& url, const std::string& data,
      const std::vector<std::string>& headers) override {
    return RetryImpl<Json::Value>(
        [&, this]() { return inner_curl_.PostToJson(url, data, headers); });
  }

  CurlResponse<std::string> DownloadToFile(
      const std::string& url, const std::string& path,
      const std::vector<std::string>& headers) {
    return RetryImpl<std::string>(
        [&, this]() { return inner_curl_.DownloadToFile(url, path, headers); });
  }

  CurlResponse<std::string> DownloadToString(
      const std::string& url, const std::vector<std::string>& headers) {
    return RetryImpl<std::string>(
        [&, this]() { return inner_curl_.DownloadToString(url, headers); });
  }

  CurlResponse<Json::Value> DownloadToJson(
      const std::string& url, const std::vector<std::string>& headers) {
    return RetryImpl<Json::Value>(
        [&, this]() { return inner_curl_.DownloadToJson(url, headers); });
  }

  CurlResponse<bool> DownloadToCallback(
      DataCallback cb, const std::string& url,
      const std::vector<std::string>& hdrs) override {
    return RetryImpl<bool>(
        [&, this]() { return inner_curl_.DownloadToCallback(cb, url, hdrs); });
  }
  CurlResponse<Json::Value> DeleteToJson(
      const std::string& url,
      const std::vector<std::string>& headers) override {
    return RetryImpl<Json::Value>(
        [&, this]() { return inner_curl_.DeleteToJson(url, headers); });
  }

  std::string UrlEscape(const std::string& text) override {
    return inner_curl_.UrlEscape(text);
  }

 private:
  template <typename T>
  CurlResponse<T> RetryImpl(std::function<CurlResponse<T>()> attempt_fn) {
    CurlResponse<T> response;
    for (int attempt = 0; attempt != retry_attempts_; ++attempt) {
      if (attempt != 0) {
        std::this_thread::sleep_for(retry_delay_);
      }
      response = attempt_fn();
      if (!response.HttpServerError()) {
        return response;
      }
    }
    return response;
  }

 private:
  CurlWrapper& inner_curl_;
  int retry_attempts_;
  std::chrono::milliseconds retry_delay_;
};

}  // namespace

/* static */ std::unique_ptr<CurlWrapper> CurlWrapper::Create() {
  return std::unique_ptr<CurlWrapper>(new CurlWrapperImpl());
}

/* static */ std::unique_ptr<CurlWrapper> CurlWrapper::WithServerErrorRetry(
    CurlWrapper& inner, int retry_attempts,
    std::chrono::milliseconds retry_delay) {
  return std::unique_ptr<CurlWrapper>(
      new CurlServerErrorRetryingWrapper(inner, retry_attempts, retry_delay));
}

CurlWrapper::~CurlWrapper() = default;
}
