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

#ifndef ENCODING_RLBE_ENCODER_H
#define ENCODING_RLBE_ENCODER_H

#include <stdint.h>

#include "bit_packing_utils.h"
#include "common/allocator/byte_stream.h"
#include "common/db_common.h"
#include "encode_utils.h"
#include "encoder.h"
#include "utils/errno_define.h"
#include "utils/util_define.h"

namespace storage {

static constexpr int RLBE_BLOCK_DEFAULT_SIZE = 10000;

template <typename T>
struct RLBETraits;

template <>
struct RLBETraits<int32_t> {
    using Unsigned = uint32_t;
    static constexpr int VALUE_BITS = 32;
    static constexpr int LENGTH_CODE_BITS = 6;
};

template <>
struct RLBETraits<int64_t> {
    using Unsigned = uint64_t;
    static constexpr int VALUE_BITS = 64;
    static constexpr int LENGTH_CODE_BITS = 7;
};

template <typename T>
class RLBEEncoder : public Encoder {
   public:
    using Traits = RLBETraits<T>;
    using Unsigned = typename Traits::Unsigned;

    RLBEEncoder() { reset(); }
    ~RLBEEncoder() override = default;

    void destroy() override {}

    void reset() override {
        type_ = common::RLBE;
        write_index_ = -1;
        previous_value_ = 0;
        byte_writer_.reset();
        for (int i = 0; i <= RLBE_BLOCK_DEFAULT_SIZE; ++i) {
            diff_value_[i] = 0;
            length_code_[i] = 0;
            length_rle_[i] = 0;
        }
    }

    int flush(common::ByteStream& out) override { return flush_block(out); }

    int get_max_byte_size() override {
        return 5 * 4 * RLBE_BLOCK_DEFAULT_SIZE *
               (Traits::VALUE_BITS == 64 ? 2 : 1);
    }

    int encode(bool, common::ByteStream&) override {
        return common::E_TYPE_NOT_MATCH;
    }
    int encode(int32_t, common::ByteStream&) override {
        return common::E_TYPE_NOT_MATCH;
    }
    int encode(int64_t, common::ByteStream&) override {
        return common::E_TYPE_NOT_MATCH;
    }
    int encode(float, common::ByteStream&) override {
        return common::E_TYPE_NOT_MATCH;
    }
    int encode(double, common::ByteStream&) override {
        return common::E_TYPE_NOT_MATCH;
    }
    int encode(common::String, common::ByteStream&) override {
        return common::E_TYPE_NOT_MATCH;
    }

   protected:
    int encode_value(T value, common::ByteStream& out) {
        if (write_index_ == -1) {
            diff_value_[++write_index_] = value;
            length_code_[write_index_] = binary_length(value);
            previous_value_ = value;
            return common::E_OK;
        }

        diff_value_[++write_index_] =
            static_cast<T>(static_cast<Unsigned>(value) -
                           static_cast<Unsigned>(previous_value_));
        length_code_[write_index_] = binary_length(diff_value_[write_index_]);
        previous_value_ = value;
        if (write_index_ == RLBE_BLOCK_DEFAULT_SIZE - 1) {
            return flush(out);
        }
        return common::E_OK;
    }

   private:
    int binary_length(T value) const {
        if (value == 0) {
            return 1;
        }
        return Traits::VALUE_BITS - number_of_leading_zeros(value);
    }

    Unsigned java_rlbe_delta_bits(T value, int bit_width) const {
        Unsigned bits = static_cast<Unsigned>(value);
        if (bit_width == Traits::VALUE_BITS) {
            bits &= ~(static_cast<Unsigned>(1) << (Traits::VALUE_BITS - 1));
        }
        return bits;
    }

    uint64_t calc_fibonacci(uint64_t value) const {
        uint64_t fib[RLBE_BLOCK_DEFAULT_SIZE * 2 + 1] = {0};
        fib[0] = 1;
        fib[1] = 1;
        int i = 0;
        for (i = 2; fib[i - 1] <= value; ++i) {
            fib[i] = fib[i - 1] + fib[i - 2];
        }
        --i;

        uint64_t encoded = 0;
        while (value > 0) {
            while (fib[i] > value && i >= 1) {
                --i;
            }
            encoded |= (1ULL << (i - 1));
            value -= fib[i];
        }
        return encoded;
    }

    void rle_on_length_code() {
        int i = 0;
        while (i <= write_index_) {
            int j = i;
            int repeat = 0;
            while (j <= write_index_ && length_code_[j] == length_code_[i]) {
                ++j;
                ++repeat;
            }
            length_rle_[i] = repeat;
            i = j;
        }
    }

    int flush_block(common::ByteStream& out) {
        int ret = common::E_OK;
        if (write_index_ == -1) {
            return common::E_OK;
        }
        if (RET_FAIL(byte_writer_.write_bits(
                static_cast<uint32_t>(write_index_ + 1), 32, out))) {
            return ret;
        }
        rle_on_length_code();
        for (int i = 0; i <= write_index_; ++i) {
            if (length_rle_[i] > 0 && RET_FAIL(flush_segment(i, out))) {
                return ret;
            }
        }
        if (RET_FAIL(byte_writer_.flush_partial(out))) {
            return ret;
        }
        reset();
        return common::E_OK;
    }

    int flush_segment(int first, common::ByteStream& out) {
        int ret = common::E_OK;
        if (RET_FAIL(byte_writer_.write_bits(
                static_cast<uint64_t>(length_code_[first]),
                Traits::LENGTH_CODE_BITS, out))) {
            return ret;
        }

        uint64_t fib = calc_fibonacci(length_rle_[first]);
        int fib_len = binary_length(static_cast<T>(fib));
        for (int i = 0; i < fib_len; ++i) {
            if (RET_FAIL(
                    byte_writer_.write_bit(((fib >> i) & 1ULL) != 0, out))) {
                return ret;
            }
        }
        if (RET_FAIL(byte_writer_.write_bit(true, out))) {
            return ret;
        }

        int j = first;
        do {
            int diff_len = binary_length(diff_value_[j]);
            if (RET_FAIL(byte_writer_.write_bits(
                    java_rlbe_delta_bits(diff_value_[j], diff_len), diff_len,
                    out))) {
                return ret;
            }
            ++j;
        } while (j <= write_index_ && length_rle_[j] == 0);
        return common::E_OK;
    }

   protected:
    common::TSEncoding type_;
    T diff_value_[RLBE_BLOCK_DEFAULT_SIZE + 1];
    int length_code_[RLBE_BLOCK_DEFAULT_SIZE + 1];
    int length_rle_[RLBE_BLOCK_DEFAULT_SIZE + 1];
    T previous_value_;
    int write_index_;
    MsbBitWriter byte_writer_;
};

class IntRLBEEncoder : public RLBEEncoder<int32_t> {
   public:
    int encode(int32_t value, common::ByteStream& out) override {
        return encode_value(value, out);
    }
};

class LongRLBEEncoder : public RLBEEncoder<int64_t> {
   public:
    int encode(int64_t value, common::ByteStream& out) override {
        return encode_value(value, out);
    }
};

class FloatRLBEEncoder : public RLBEEncoder<int32_t> {
   public:
    int encode(float value, common::ByteStream& out) override {
        return encode_value(common::float_to_int(value), out);
    }
};

class DoubleRLBEEncoder : public RLBEEncoder<int64_t> {
   public:
    int encode(double value, common::ByteStream& out) override {
        return encode_value(common::double_to_long(value), out);
    }
};

}  // namespace storage

#endif  // ENCODING_RLBE_ENCODER_H
