/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 <assert.h>
#include <curl/curl.h>

#include <string>

namespace pulsar {

struct CurlInitializer {
    CurlInitializer() { curl_global_init(CURL_GLOBAL_ALL); }
    ~CurlInitializer() { curl_global_cleanup(); }
};
static CurlInitializer curlInitializer;

class CurlWrapper {
   public:
    CurlWrapper() noexcept {}
    ~CurlWrapper() {
        if (handle_) {
            curl_easy_cleanup(handle_);
        }
    }

    char* escape(const std::string& s) const {
        assert(handle_);
        return curl_easy_escape(handle_, s.c_str(), s.length());
    }

    // It must be called before calling other methods
    bool init() {
        handle_ = curl_easy_init();
        return handle_ != nullptr;
    }

    struct Options {
        std::string method;
        std::string postFields;
        std::string userAgent;
        int timeoutInSeconds{0};
        int maxLookupRedirects{-1};
    };

    struct TlsContext {
        std::string trustCertsFilePath;
        bool validateHostname{true};
        bool allowInsecure{false};
        std::string certPath;
        std::string keyPath;
    };

    struct Result {
        CURLcode code;
        std::string responseData;
        long responseCode;
        std::string redirectUrl;
        std::string error;
        std::string serverError;
    };

    Result get(const std::string& url, const std::string& header, const Options& options,
               const TlsContext* tlsContext) const;

   private:
    CURL* handle_;

    struct CurlListGuard {
        curl_slist*& headers;

        CurlListGuard(curl_slist*& headers) : headers(headers) {}
        ~CurlListGuard() {
            if (headers) {
                curl_slist_free_all(headers);
            }
        }
    };
};

inline CurlWrapper::Result CurlWrapper::get(const std::string& url, const std::string& header,
                                            const Options& options, const TlsContext* tlsContext) const {
    assert(handle_);
    curl_easy_setopt(handle_, CURLOPT_URL, url.c_str());

    if (!options.postFields.empty()) {
        curl_easy_setopt(handle_, CURLOPT_CUSTOMREQUEST, "POST");
        curl_easy_setopt(handle_, CURLOPT_POSTFIELDS, options.postFields.c_str());
    }

    // Write response
    curl_easy_setopt(
        handle_, CURLOPT_WRITEFUNCTION,
        +[](char* buffer, size_t size, size_t nitems, void* outstream) -> size_t {
            static_cast<std::string*>(outstream)->append(buffer, size * nitems);
            return size * nitems;
        });
    std::string response;
    curl_easy_setopt(handle_, CURLOPT_WRITEDATA, &response);

    // New connection is made for each call
    curl_easy_setopt(handle_, CURLOPT_FRESH_CONNECT, 1L);
    curl_easy_setopt(handle_, CURLOPT_FORBID_REUSE, 1L);

    // Skipping signal handling - results in timeouts not honored during the DNS lookup
    // Without this config, Curl_resolv_timeout might crash in multi-threads environment
    curl_easy_setopt(handle_, CURLOPT_NOSIGNAL, 1L);

    curl_easy_setopt(handle_, CURLOPT_TIMEOUT, options.timeoutInSeconds);
    if (!options.userAgent.empty()) {
        curl_easy_setopt(handle_, CURLOPT_USERAGENT, options.userAgent.c_str());
    }
    curl_easy_setopt(handle_, CURLOPT_FAILONERROR, 1L);

    // Redirects
    curl_easy_setopt(handle_, CURLOPT_FOLLOWLOCATION, 1L);
    curl_easy_setopt(handle_, CURLOPT_MAXREDIRS, options.maxLookupRedirects);

    char errorBuffer[CURL_ERROR_SIZE] = "";
    curl_easy_setopt(handle_, CURLOPT_ERRORBUFFER, errorBuffer);

    curl_slist* headers = nullptr;
    CurlListGuard headersGuard{headers};
    if (!header.empty()) {
        headers = curl_slist_append(headers, header.c_str());
        curl_easy_setopt(handle_, CURLOPT_HTTPHEADER, headers);
    }

    if (tlsContext) {
        CURLcode code;
        code = curl_easy_setopt(handle_, CURLOPT_SSLENGINE, nullptr);
        if (code != CURLE_OK) {
            return {code, "", -1, "",
                    "Unable to load SSL engine for url " + url + ": " + curl_easy_strerror(code)};
        }
        code = curl_easy_setopt(handle_, CURLOPT_SSLENGINE_DEFAULT, 1L);
        if (code != CURLE_OK) {
            return {code, "", -1, "",
                    "Unable to load SSL engine as default for url " + url + ": " + curl_easy_strerror(code)};
        }
        curl_easy_setopt(handle_, CURLOPT_SSL_VERIFYHOST, tlsContext->validateHostname ? 1L : 0L);
        curl_easy_setopt(handle_, CURLOPT_SSL_VERIFYPEER, tlsContext->allowInsecure ? 0L : 1L);
        if (!tlsContext->trustCertsFilePath.empty()) {
            curl_easy_setopt(handle_, CURLOPT_CAINFO, tlsContext->trustCertsFilePath.c_str());
        }
        if (!tlsContext->certPath.empty() && !tlsContext->keyPath.empty()) {
            curl_easy_setopt(handle_, CURLOPT_SSLCERT, tlsContext->certPath.c_str());
            curl_easy_setopt(handle_, CURLOPT_SSLKEY, tlsContext->keyPath.c_str());
        }
    }

    auto res = curl_easy_perform(handle_);
    long responseCode;
    curl_easy_getinfo(handle_, CURLINFO_RESPONSE_CODE, &responseCode);
    Result result{res, response, responseCode, "", "", std::string(errorBuffer)};
    if (responseCode == 307 || responseCode == 302 || responseCode == 301) {
        char* url;
        curl_easy_getinfo(handle_, CURLINFO_REDIRECT_URL, &url);
        // `url` is null when the host of the redirect URL cannot be resolved
        if (url) {
            result.redirectUrl = url;
        }
    }
    return result;
}

}  // namespace pulsar
