// 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 <gtest/gtest-message.h>
#include <gtest/gtest-test-part.h>

#include <cstdint>
#include <iostream>

#include "gtest/gtest_pred_impl.h"
#include "vec/common/ipv6_to_binary.h"
#include "vec/runtime/ipv4_value.h"
#include "vec/runtime/ipv6_value.h"

namespace doris {

class IPv4Value;
class IPv6Value;

// util function
template <typename T>
static void print_bytes(T num) {
    auto* byte_ptr = reinterpret_cast<uint8_t*>(&num);

    std::cout << "low -> ";

    for (size_t i = 0; i < sizeof(T); ++i) {
        std::cout << std::hex << static_cast<int>(byte_ptr[i]) << " ";
    }

    std::cout << " -> high";
    std::cout << std::dec << std::endl;
}

TEST(IPValueTest, IPv4ValueTest) {
    const std::string ipv4_str1 = "192.168.103.254";
    const std::string ipv4_str2 = "193.168.103.255";
    IPv4 ipv4_val1;
    IPv4 ipv4_val2;
    ASSERT_TRUE(IPv4Value::from_string(ipv4_val1, ipv4_str1.c_str(), ipv4_str1.size()));
    ASSERT_TRUE(IPv4Value::from_string(ipv4_val2, ipv4_str2.c_str(), ipv4_str2.size()));
    ASSERT_TRUE(ipv4_val1 < ipv4_val2);
    print_bytes(ipv4_val1);
    print_bytes(ipv4_val2);
    std::string ipv4_format1 = IPv4Value::to_string(ipv4_val1);
    std::string ipv4_format2 = IPv4Value::to_string(ipv4_val2);
    ASSERT_EQ(ipv4_str1, ipv4_format1);
    ASSERT_EQ(ipv4_str2, ipv4_format2);
}

TEST(IPValueTest, IPv6ValueTest) {
    const std::string ipv6_str1 = "2001:418:0:5000::c2d";
    const std::string ipv6_str2 = "2001:428::205:171:200:230";
    IPv6 ipv6_val1;
    IPv6 ipv6_val2;
    ASSERT_TRUE(IPv6Value::from_string(ipv6_val1, ipv6_str1.c_str(), ipv6_str1.size()));
    ASSERT_TRUE(IPv6Value::from_string(ipv6_val2, ipv6_str2.c_str(), ipv6_str2.size()));
    ASSERT_TRUE(ipv6_val1 < ipv6_val2);
    print_bytes(ipv6_val1);
    print_bytes(ipv6_val2);
    std::string ipv6_format1 = IPv6Value::to_string(ipv6_val1);
    std::string ipv6_format2 = IPv6Value::to_string(ipv6_val2);
    ASSERT_EQ(ipv6_str1, ipv6_format1);
    ASSERT_EQ(ipv6_str2, ipv6_format2);
}

static void apply_cidr_mask(const char* __restrict src, char* __restrict dst_lower,
                            char* __restrict dst_upper, vectorized::UInt8 bits_to_keep) {
    const auto& mask = vectorized::get_cidr_mask_ipv6(bits_to_keep);

    for (int8_t i = IPV6_BINARY_LENGTH - 1; i >= 0; --i) {
        dst_lower[i] = src[i] & mask[i];
        dst_upper[i] = dst_lower[i] | ~mask[i];
    }
}

TEST(IPValueTest, IPv6CIDRTest) {
    const std::string ipv6_str1 = "2001:0db8:0000:85a3:0000:0000:ac1f:8001";
    const std::string ipv6_str2 = "2001:0db8:0000:85a3:ffff:ffff:ffff:ffff";
    IPv6 ipv6_val1; // little-endian
    IPv6 ipv6_val2; // little-endian
    ASSERT_TRUE(IPv6Value::from_string(ipv6_val1, ipv6_str1.c_str(), ipv6_str1.size()));
    ASSERT_TRUE(IPv6Value::from_string(ipv6_val2, ipv6_str2.c_str(), ipv6_str2.size()));
    IPv6 min_range1, max_range1;
    IPv6 min_range2, max_range2;
    apply_cidr_mask(reinterpret_cast<const char*>(&ipv6_val1), reinterpret_cast<char*>(&min_range1),
                    reinterpret_cast<char*>(&max_range1), 0);
    apply_cidr_mask(reinterpret_cast<const char*>(&ipv6_val2), reinterpret_cast<char*>(&min_range2),
                    reinterpret_cast<char*>(&max_range2), 32);
    print_bytes(min_range1);
    print_bytes(max_range1);
    print_bytes(min_range2);
    print_bytes(max_range2);
    std::string min_range_format1 = IPv6Value::to_string(min_range1);
    std::string max_range_format1 = IPv6Value::to_string(max_range1);
    std::string min_range_format2 = IPv6Value::to_string(min_range2);
    std::string max_range_format2 = IPv6Value::to_string(max_range2);
    ASSERT_EQ(min_range_format1, "::");
    ASSERT_EQ(max_range_format1, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
    ASSERT_EQ(min_range_format2, "2001:db8::");
    ASSERT_EQ(max_range_format2, "2001:db8:ffff:ffff:ffff:ffff:ffff:ffff");
}

} // namespace doris