/*
 * 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 "paimon/utils/roaring_bitmap32.h"

#include <cassert>
#include <memory>
#include <utility>

#include "paimon/fs/file_system.h"
#include "paimon/io/byte_array_input_stream.h"
#include "paimon/result.h"
#include "roaring.hh"  // NOLINT(build/include_subdir)

namespace paimon {
namespace {
roaring::Roaring::const_iterator& GetIterator(void* iter) {
    return *(static_cast<roaring::Roaring::const_iterator*>(iter));
}
roaring::Roaring& GetRoaringBitmap(void* bitmap) {
    return *(static_cast<roaring::Roaring*>(bitmap));
}
}  // namespace

RoaringBitmap32::Iterator::Iterator(const RoaringBitmap32& bitmap) {
    iterator_ =
        new roaring::Roaring::const_iterator(GetRoaringBitmap(bitmap.roaring_bitmap_).begin());
}

RoaringBitmap32::Iterator::~Iterator() {
    if (iterator_) {
        delete static_cast<roaring::Roaring::const_iterator*>(iterator_);
    }
}

RoaringBitmap32::Iterator::Iterator(const RoaringBitmap32::Iterator& other) noexcept {
    *this = other;
}
RoaringBitmap32::Iterator& RoaringBitmap32::Iterator::operator=(
    const RoaringBitmap32::Iterator& other) noexcept {
    if (&other == this) {
        return *this;
    }
    if (!iterator_) {
        iterator_ = new roaring::Roaring::const_iterator(GetIterator(other.iterator_));
    } else {
        GetIterator(iterator_) = GetIterator(other.iterator_);
    }
    return *this;
}

RoaringBitmap32::Iterator::Iterator(RoaringBitmap32::Iterator&& other) noexcept {
    *this = std::move(other);
}

RoaringBitmap32::Iterator& RoaringBitmap32::Iterator::operator=(
    RoaringBitmap32::Iterator&& other) noexcept {
    if (&other == this) {
        return *this;
    }
    if (iterator_) {
        delete static_cast<roaring::Roaring::const_iterator*>(iterator_);
    }
    iterator_ = other.iterator_;
    other.iterator_ = nullptr;
    return *this;
}

int32_t RoaringBitmap32::Iterator::operator*() const {
    return *GetIterator(iterator_);
}
RoaringBitmap32::Iterator& RoaringBitmap32::Iterator::operator++() {
    ++GetIterator(iterator_);
    return *this;
}
bool RoaringBitmap32::Iterator::operator==(const Iterator& other) const {
    if (&other == this) {
        return true;
    }
    assert(iterator_ && other.iterator_);
    return GetIterator(iterator_) == GetIterator(other.iterator_);
}
bool RoaringBitmap32::Iterator::operator!=(const Iterator& other) const {
    return !(*this == other);
}

RoaringBitmap32::RoaringBitmap32() {
    roaring_bitmap_ = new roaring::Roaring();
}
RoaringBitmap32::~RoaringBitmap32() {
    if (roaring_bitmap_) {
        delete static_cast<roaring::Roaring*>(roaring_bitmap_);
    }
}

RoaringBitmap32::RoaringBitmap32(const RoaringBitmap32& other) noexcept {
    *this = other;
}
RoaringBitmap32& RoaringBitmap32::operator=(const RoaringBitmap32& other) noexcept {
    if (&other == this) {
        return *this;
    }
    if (!roaring_bitmap_) {
        roaring_bitmap_ = new roaring::Roaring(GetRoaringBitmap(other.roaring_bitmap_));
    } else {
        GetRoaringBitmap(roaring_bitmap_) = GetRoaringBitmap(other.roaring_bitmap_);
    }
    return *this;
}

RoaringBitmap32::RoaringBitmap32(RoaringBitmap32&& other) noexcept {
    *this = std::move(other);
}

RoaringBitmap32& RoaringBitmap32::operator=(RoaringBitmap32&& other) noexcept {
    if (&other == this) {
        return *this;
    }
    if (roaring_bitmap_) {
        delete static_cast<roaring::Roaring*>(roaring_bitmap_);
    }
    roaring_bitmap_ = other.roaring_bitmap_;
    other.roaring_bitmap_ = nullptr;
    return *this;
}

RoaringBitmap32& RoaringBitmap32::operator|=(const RoaringBitmap32& other) {
    GetRoaringBitmap(roaring_bitmap_) |= GetRoaringBitmap(other.roaring_bitmap_);
    return *this;
}
RoaringBitmap32& RoaringBitmap32::operator&=(const RoaringBitmap32& other) {
    GetRoaringBitmap(roaring_bitmap_) &= GetRoaringBitmap(other.roaring_bitmap_);
    return *this;
}
RoaringBitmap32& RoaringBitmap32::operator-=(const RoaringBitmap32& other) {
    GetRoaringBitmap(roaring_bitmap_) -= GetRoaringBitmap(other.roaring_bitmap_);
    return *this;
}

void RoaringBitmap32::Add(int32_t x) {
    GetRoaringBitmap(roaring_bitmap_).add(x);
}

void RoaringBitmap32::AddRange(int32_t min, int32_t max) {
    GetRoaringBitmap(roaring_bitmap_).addRange(min, max);
}

void RoaringBitmap32::RemoveRange(int32_t min, int32_t max) {
    GetRoaringBitmap(roaring_bitmap_).removeRange(min, max);
}

bool RoaringBitmap32::ContainsAny(int32_t min, int32_t max) const {
    auto iter = EqualOrLarger(min);
    if (iter != End() && *iter < max) {
        return true;
    }
    return false;
}

bool RoaringBitmap32::CheckedAdd(int32_t x) {
    if (Contains(x)) {
        return false;
    }
    Add(x);
    return true;
}

int32_t RoaringBitmap32::Cardinality() const {
    return GetRoaringBitmap(roaring_bitmap_).cardinality();
}

bool RoaringBitmap32::Contains(int32_t x) const {
    return GetRoaringBitmap(roaring_bitmap_).contains(x);
}

bool RoaringBitmap32::IsEmpty() const {
    return GetRoaringBitmap(roaring_bitmap_).isEmpty();
}

size_t RoaringBitmap32::GetSizeInBytes() const {
    return GetRoaringBitmap(roaring_bitmap_).getSizeInBytes();
}

void RoaringBitmap32::Flip(int32_t min, int32_t max) {
    GetRoaringBitmap(roaring_bitmap_).flip(min, max);
}

bool RoaringBitmap32::operator==(const RoaringBitmap32& other) const noexcept {
    if (this == &other) {
        return true;
    }
    assert(roaring_bitmap_ && other.roaring_bitmap_);
    return GetRoaringBitmap(roaring_bitmap_) == GetRoaringBitmap(other.roaring_bitmap_);
}

PAIMON_UNIQUE_PTR<Bytes> RoaringBitmap32::Serialize(MemoryPool* pool) const {
    GetRoaringBitmap(roaring_bitmap_).runOptimize();
    auto& bitmap = GetRoaringBitmap(roaring_bitmap_);
    // Use default pool if no pool is provided
    if (pool == nullptr) {
        pool = GetDefaultPool().get();
    }
    auto bytes = Bytes::AllocateBytes(bitmap.getSizeInBytes(), pool);
    bitmap.write(bytes->data());
    return bytes;
}

Status RoaringBitmap32::Deserialize(ByteArrayInputStream* input_stream) {
    const char* data = input_stream->GetRawData();
    PAIMON_ASSIGN_OR_RAISE(int64_t pos, input_stream->GetPos());
    PAIMON_ASSIGN_OR_RAISE(int64_t total_length, input_stream->Length());
    try {
        GetRoaringBitmap(roaring_bitmap_) =
            roaring::Roaring::readSafe(data, /*maxbytes=*/total_length - pos);
    } catch (...) {
        return Status::Invalid("catch exception in Deserialize() of RoaringBitmap32");
    }
    return input_stream->Seek(GetRoaringBitmap(roaring_bitmap_).getSizeInBytes(),
                              SeekOrigin::FS_SEEK_CUR);
}

Status RoaringBitmap32::Deserialize(const char* begin, size_t length) {
    try {
        GetRoaringBitmap(roaring_bitmap_) = roaring::Roaring::readSafe(begin, length);
    } catch (...) {
        return Status::Invalid("catch exception in Deserialize() of RoaringBitmap32");
    }
    return Status::OK();
}

std::string RoaringBitmap32::ToString() const {
    return GetRoaringBitmap(roaring_bitmap_).toString();
}

RoaringBitmap32 RoaringBitmap32::And(const RoaringBitmap32& lhs, const RoaringBitmap32& rhs) {
    RoaringBitmap32 res;
    GetRoaringBitmap(res.roaring_bitmap_) =
        (GetRoaringBitmap(lhs.roaring_bitmap_) & GetRoaringBitmap(rhs.roaring_bitmap_));
    return res;
}

RoaringBitmap32 RoaringBitmap32::Or(const RoaringBitmap32& lhs, const RoaringBitmap32& rhs) {
    RoaringBitmap32 res;
    GetRoaringBitmap(res.roaring_bitmap_) =
        (GetRoaringBitmap(lhs.roaring_bitmap_) | GetRoaringBitmap(rhs.roaring_bitmap_));
    return res;
}

RoaringBitmap32 RoaringBitmap32::AndNot(const RoaringBitmap32& lhs, const RoaringBitmap32& rhs) {
    RoaringBitmap32 res;
    GetRoaringBitmap(res.roaring_bitmap_) =
        (GetRoaringBitmap(lhs.roaring_bitmap_) - GetRoaringBitmap(rhs.roaring_bitmap_));
    return res;
}

RoaringBitmap32 RoaringBitmap32::From(const std::vector<int32_t>& values) {
    RoaringBitmap32 res;
    for (const auto& value : values) {
        res.Add(value);
    }
    return res;
}

RoaringBitmap32 RoaringBitmap32::FastUnion(const std::vector<const RoaringBitmap32*>& inputs) {
    std::vector<roaring::Roaring*> roaring_inputs;
    roaring_inputs.reserve(inputs.size());
    for (const auto* roaring : inputs) {
        roaring_inputs.push_back(&GetRoaringBitmap(roaring->roaring_bitmap_));
    }
    RoaringBitmap32 res;
    GetRoaringBitmap(res.roaring_bitmap_) = roaring::Roaring::fastunion(
        roaring_inputs.size(), const_cast<const roaring::Roaring**>(roaring_inputs.data()));
    return res;
}

RoaringBitmap32 RoaringBitmap32::FastUnion(const std::vector<RoaringBitmap32>& inputs) {
    std::vector<const RoaringBitmap32*> inputs_ptr;
    inputs_ptr.reserve(inputs.size());
    for (const auto& bitmap : inputs) {
        inputs_ptr.push_back(&bitmap);
    }
    return FastUnion(inputs_ptr);
}
RoaringBitmap32::Iterator RoaringBitmap32::Begin() const {
    return RoaringBitmap32::Iterator(*this);
}

RoaringBitmap32::Iterator RoaringBitmap32::End() const {
    RoaringBitmap32::Iterator iter(*this);
    GetIterator(iter.iterator_) = GetRoaringBitmap(roaring_bitmap_).end();
    return iter;
}

RoaringBitmap32::Iterator RoaringBitmap32::EqualOrLarger(int32_t key) const {
    RoaringBitmap32::Iterator iter(*this);
    GetIterator(iter.iterator_).equalorlarger(key);
    return iter;
}

}  // namespace paimon
