// 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.

#include "util/url_coding.h"

#include <curl/curl.h>
#include <libbase64.h>

#include <cmath>
#include <sstream>

namespace doris {

inline unsigned char to_hex(unsigned char x) {
    return x + (x > 9 ? ('A' - 10) : '0');
}

// Adapted from http://dlib.net/dlib/server/server_http.cpp.html
void url_encode(const std::string_view& in, std::string* out) {
    std::ostringstream os;
    for (auto c : in) {
        // impl as https://docs.oracle.com/javase/8/docs/api/java/net/URLEncoder.html
        if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') ||
            c == '.' || c == '-' || c == '*' || c == '_') { // allowed
            os << c;
        } else if (c == ' ') {
            os << '+';
        } else {
            ///TODO: In the past, there was an error here involving the modulus operation on a char (signed number).
            // When the char data exceeds 128 (UTF-8 byte), it leads to incorrect results. It is actually better to use some third-party libraries here.
            os << '%' << to_hex((unsigned char)c >> 4) << to_hex((unsigned char)c % 16);
        }
    }

    *out = os.str();
}

// Adapted from
// http://www.boost.org/doc/libs/1_40_0/doc/html/boost_asio/
//   example/http/server3/request_handler.cpp
// See http://www.boost.org/LICENSE_1_0.txt for license for this method.
// Value of a single hexadecimal digit, or -1 when c is not one.
static int hex_digit(char c) {
    if (c >= '0' && c <= '9') {
        return c - '0';
    }
    if (c >= 'a' && c <= 'f') {
        return c - 'a' + 10;
    }
    if (c >= 'A' && c <= 'F') {
        return c - 'A' + 10;
    }
    return -1;
}

bool url_decode(const std::string& in, std::string* out) {
    out->clear();
    out->reserve(in.size());

    for (size_t i = 0; i < in.size(); ++i) {
        if (in[i] == '%') {
            if (i + 3 > in.size()) {
                return false;
            }

            // A '%' must be followed by exactly two hexadecimal digits. Parsing the pair
            // with a stream accepts a partial match such as "%1g" and silently drops the
            // character that follows it.
            const int high = hex_digit(in[i + 1]);
            const int low = hex_digit(in[i + 2]);
            if (high < 0 || low < 0) {
                return false;
            }

            (*out) += static_cast<char>((high << 4) | low);
            i += 2;
        } else if (in[i] == '+') {
            (*out) += ' ';
        } else {
            (*out) += in[i];
        }
    }

    return true;
}

void base64_encode(const std::string& in, std::string* out) {
    out->resize((size_t)(4.0 * std::ceil(in.length() / 3.0)));
    auto len = base64_encode(reinterpret_cast<const unsigned char*>(in.data()), in.length(),
                             (unsigned char*)out->data());
    out->resize(len);
}

size_t base64_encode(const unsigned char* data, size_t length, unsigned char* encoded_data) {
    size_t encode_len = 0;
#if defined(__aarch64__) || defined(_M_ARM64)
    do_base64_encode(reinterpret_cast<const char*>(data), length,
                     reinterpret_cast<char*>(encoded_data), &encode_len, BASE64_FORCE_NEON64);
#else
    do_base64_encode(reinterpret_cast<const char*>(data), length,
                     reinterpret_cast<char*>(encoded_data), &encode_len, 0);
#endif
    return encode_len;
}

int64_t base64_decode(const char* data, size_t length, char* decoded_data) {
    size_t decode_len = 0;
#if defined(__aarch64__) || defined(_M_ARM64)
    auto ret = do_base64_decode(reinterpret_cast<const char*>(data), length, decoded_data,
                                &decode_len, BASE64_FORCE_NEON64);
#else
    auto ret = do_base64_decode(data, length, decoded_data, &decode_len, 0);
#endif
    return ret > 0 ? decode_len : -1;
}

bool base64_decode(const std::string& in, std::string* out) {
    out->resize(in.length());

    int64_t len = base64_decode(in.data(), in.length(), out->data());
    if (len < 0) {
        return false;
    }
    out->resize(len);
    return true;
}

void escape_for_html(const std::string& in, std::stringstream* out) {
    for (const auto& c : in) {
        switch (c) {
        case '<':
            (*out) << "&lt;";
            break;

        case '>':
            (*out) << "&gt;";
            break;

        case '&':
            (*out) << "&amp;";
            break;

        default:
            (*out) << c;
        }
    }
}

std::string escape_for_html_to_string(const std::string& in) {
    std::stringstream str;
    escape_for_html(in, &str);
    return str.str();
}
} // namespace doris
