/*
 * 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 "SparkFunctionConv.h"
#include <string>
#include <DataTypes/DataTypeNullable.h>
#include <Functions/FunctionFactory.h>
#include <Poco/Logger.h>
#include <Poco/Types.h>
#include <Common/Exception.h>
#include <Common/logger_useful.h>
#include <DataTypes/IDataType.h>
#include <base/types.h>

namespace DB
{
namespace ErrorCodes
{
    extern const int ILLEGAL_TYPE_OF_ARGUMENT;
    extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH;
}
}

namespace local_engine
{

DB::DataTypePtr SparkFunctionConv::getReturnTypeImpl(const DB::DataTypes & arguments) const
{
    if (arguments.size() != 3)
        throw DB::Exception(DB::ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH,
            "Number of arguments for function {} doesn't match: passed {}, should be 3.",
            getName(), arguments.size());

    if (!isInteger(arguments[1]))
        throw DB::Exception(DB::ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
            "Second argument for function {} must be Int", getName());
    if (!isInteger(arguments[2]))
        throw DB::Exception(DB::ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
            "Third argument for function {} must be Int", getName());

    auto arg0_type = DB::removeNullable(arguments[0]);
    return std::make_shared<DB::DataTypeNullable>(arg0_type);
}

/// Taken from mysql-server sql/item_strfunc.cc
static unsigned long long my_strntoull_8bit(const char *nptr,
                                     size_t l, int base, const char **endptr,
                                     int *err)
{
    int negative;
    unsigned long long cutoff = 0;
    unsigned cutlim = 0;
    unsigned long long i = 0;
    const char *save = nullptr;
    int overflow = 0;

    *err = 0; /* Initialize error indicator */

    const char *s = nptr;
    const char *e = nptr + l;

    for (; s < e && std::isspace(*s); s++)
        ;

    if (s == e)
    {
        err[0] = EDOM;
        goto noconv;
    }

    if (*s == '-')
    {
        negative = 1;
        ++s;
    } else if (*s == '+') {
        negative = 0;
        ++s;
    } else
        negative = 0;

    save = s;

    cutoff = (~static_cast<unsigned long long>(0)) / static_cast<unsigned long int>(base);
    cutlim = static_cast<unsigned>(((~static_cast<unsigned long long>(0)) % static_cast<unsigned long int>(base)));

    overflow = 0;
    i = 0;
    for (; s != e; s++) {
        uint8_t c = *s;

        if (c >= '0' && c <= '9')
            c -= '0';
        else if (c >= 'A' && c <= 'Z')
            c = c - 'A' + 10;
        else if (c >= 'a' && c <= 'z')
            c = c - 'a' + 10;
        else
            break;
        if (c >= base) break;
        if (i > cutoff || (i == cutoff && c > cutlim))
            overflow = 1;
        else
        {
            i *= static_cast<unsigned long long>(base);
            i += c;
        }
    }

    if (s == save) goto noconv;

    if (endptr != nullptr) *endptr = s;

    if (overflow)
    {
        err[0] = ERANGE;
        return (~static_cast<unsigned long long>(0));
    }

    return negative ? -i : i;

noconv:
    if (endptr != nullptr) *endptr = nptr;
    return 0L;
}

static char * ll2str(int64_t val, char * dst, int radix, bool upcase)
{
    constexpr std::array<const char, 37> dig_vec_upper{"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"};
    constexpr std::array<const char, 37> dig_vec_lower{"0123456789abcdefghijklmnopqrstuvwxyz"};
    char buffer[65];
    const char *const dig_vec = upcase ? dig_vec_upper.data() : dig_vec_lower.data();
    auto uval = static_cast<uint64_t>(val);

    if (radix < 0)
    {
        if (radix < -36 || radix > -2) return nullptr;
        if (val < 0)
        {
            *dst++ = '-';
            /* Avoid integer overflow in (-val) for LLONG_MIN (BUG#31799). */
            uval = 0ULL - uval;
        }
        radix = -radix;
    }
    else if (radix > 36 || radix < 2)
    {
        return nullptr;
    }

    char *p = std::end(buffer);
    do
    {
        *--p = dig_vec[uval % radix];
        uval /= radix;
    } while (uval != 0);

    const size_t length = std::end(buffer) - p;
    memcpy(dst, p, length);
    dst[length] = '\0';
    return dst + length;
}

DB::ColumnPtr SparkFunctionConv::executeImpl(
    const DB::ColumnsWithTypeAndName & arguments, const DB::DataTypePtr & result_type, size_t input_rows_count) const
{
    using longlong = Int64;
    auto from_base = static_cast<int>(arguments[1].column->getInt(0));
    auto to_base = static_cast<int>(arguments[2].column->getInt(0));

    auto result = result_type->createColumn();
    result->reserve(input_rows_count);
    // Note that abs(INT_MIN) is undefined.
    if (from_base == INT_MIN || to_base == INT_MIN || abs(to_base) > 36 || abs(to_base) < 2 || abs(from_base) > 36 || abs(from_base) < 2)
    {
        for (size_t i = 0; i < input_rows_count; ++i)
            result->insertData(nullptr, 1);
        return result;
    }

    longlong dec = 0;
    const char * endptr = nullptr;
    int err = 0;
    for (size_t i = 0; i < input_rows_count; ++i)
    {
        auto value_str = arguments[0].column->getDataAt(i).toString();
        if (from_base < 0)
            dec = my_strntoull_8bit(value_str.data(), value_str.length(), -from_base, &endptr, &err);
        else
            dec = static_cast<longlong>(my_strntoull_8bit(value_str.data(), value_str.length(), from_base, &endptr, &err));
        if (err == EDOM)
        {
            result->insertData(nullptr, 1);
            continue;
        }
        char ans[CONV_MAX_LENGTH + 1U];
        auto ret_ptr = ll2str(dec, ans, to_base, true);
        if (ret_ptr == nullptr)
            result->insertData(nullptr, 1);
        else
            result->insertData(ans, ret_ptr - ans);
    }
    return result;
}

REGISTER_FUNCTION(SparkFunctionConv)
{
    factory.registerFunction<SparkFunctionConv>();
}
}
