/*
 * 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 "SparkFunctionNextDay.h"
#include <unordered_map>
#include <Columns/ColumnNullable.h>
#include <DataTypes/DataTypeDate32.h>
#include <DataTypes/DataTypeDateTime.h>
#include <DataTypes/DataTypeDateTime64.h>
#include <DataTypes/DataTypeNullable.h>
#include <Functions/DateTimeTransforms.h>
#include <Functions/FunctionFactory.h>
#include <Functions/TransformDateTime64.h>
#include <Poco/Logger.h>
#include <Common/DateLUT.h>
#include <Common/Exception.h>
#include <Common/logger_useful.h>
#include <boost/algorithm/string/case_conv.hpp>

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

namespace local_engine
{
DB::DataTypePtr SparkFunctionNextDay::getReturnTypeImpl(const DB::ColumnsWithTypeAndName & arguments) const
{
    if (arguments.size() != 2)
    {
        throw DB::Exception(DB::ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
            "Function {} requires exactly 2 arguments, {} provided",
            getName(), arguments.size());
    }
    auto arg0_type = DB::removeNullable(arguments[0].type);
    auto arg0_which_type = DB::WhichDataType(arg0_type);
    if (!arg0_which_type.isDate() && !arg0_which_type.isDate32() && !arg0_which_type.isDateTime() && !arg0_which_type.isDateTime64())
    {
        throw DB::Exception(
            DB::ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
            "Illegal type {} of argument[0] of function {}",
            arguments[0].type->getName(),
            getName());
    }

    auto arg1_type = DB::removeNullable(arguments[1].type);
    if (!DB::WhichDataType(arg1_type).isString())
    {
        throw DB::Exception(DB::ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
            "Illegal type {} of argument[1] of function {}",
            arguments[1].type->getName(), getName());
    }

    return DB::makeNullableSafe(arg0_type);
}

DB::ColumnPtr SparkFunctionNextDay::executeImpl(
    const DB::ColumnsWithTypeAndName & arguments, const DB::DataTypePtr & result_type, size_t /*input_rows_count*/) const
{
    if (DB::isColumnConst(*arguments[1].column))
    {
        return executeConst(arguments, result_type);
    }
    else
    {
        return executeGeneral(arguments, result_type);
    }
}

struct NextDayConstTransformer
{
    static constexpr auto name = "NextDay";
    static const UInt8 week_mode = 0;

    static inline Int64 execute(Int64 day, UInt8 next_weekday, const DateLUTImpl & time_zone)
    {
        auto from_week_day = DB::ToDayOfWeekImpl::execute(day, week_mode, time_zone);
        return day + static_cast<Int64>(calDayDelta(from_week_day, next_weekday));
    }

    static inline UInt32 execute(UInt32 day, UInt8 next_weekday, const DateLUTImpl & time_zone)
    {
        auto from_week_day = DB::ToDayOfWeekImpl::execute(day, week_mode, time_zone);
        return day + static_cast<UInt32>(calDayDelta(from_week_day, next_weekday));
    }

    static inline Int32 execute(Int32 day, UInt8 next_weekday, const DateLUTImpl & time_zone)
    {
        auto from_week_day = DB::ToDayOfWeekImpl::execute(day, week_mode, time_zone);
        return day + static_cast<Int32>(calDayDelta(from_week_day, next_weekday));
    }

    static inline UInt16 execute(UInt16 day, UInt8 next_weekday, const DateLUTImpl & time_zone)
    {
        auto from_week_day = DB::ToDayOfWeekImpl::execute(day, week_mode, time_zone);
        return day + static_cast<UInt16>(calDayDelta(from_week_day, next_weekday));
    }

    static UInt16 calDayDelta(UInt16 from_week_day, UInt16 next_weekday)
    {
        return next_weekday > from_week_day ? next_weekday - from_week_day : 7 + next_weekday - from_week_day;
    }
};


template <typename DateType>
class NextDayConstImpl
{
public:
    template<typename Transformer>
    static void execute(const DB::IColumn & src_col, UInt16 next_weekday, DB::IColumn * dst_col, Transformer transformer = {})
    {
        const auto & time_zone = DateLUT::instance();
        size_t rows = src_col.size();
        for(size_t i = 0; i < rows; ++i)
        {
            DB::Field from_day_value;
            src_col.get(i, from_day_value);
            if (from_day_value.isNull())
            {
                dst_col->insertDefault();
            }
            else
            {
                dst_col->insert(transformer.execute(
                    static_cast<typename DateType::FieldType>(from_day_value.safeGet<typename DateType::FieldType>()),
                    next_weekday,
                    time_zone));
            }
        }
    }

    template<typename Transformer>
    static void execute(const DB::IColumn & src_col, const DB::IColumn & weekday_col, DB::IColumn * dst_col, Transformer transformer = {})
    {
        size_t rows = src_col.size();
        const auto & time_zone = DateLUT::instance();
        for (size_t i = 0; i < rows; ++i)
        {
            DB::Field from_day_value;
            DB::Field weekday_value;
            src_col.get(i, from_day_value);
            weekday_col.get(i, weekday_value);
            if (from_day_value.isNull() || weekday_value.isNull())
            {
                dst_col->insertDefault();
            }
            else
            {
                auto next_weekday = SparkFunctionNextDay::getDayOfWeek(weekday_value.safeGet<String>());
                if (next_weekday < 0) [[unlikely]]
                {
                    dst_col->insertDefault();
                }
                else
                {
                    dst_col->insert(transformer.execute(
                        static_cast<typename DateType::FieldType>(from_day_value.safeGet<typename DateType::FieldType>()),
                        next_weekday,
                        time_zone));
                }
            }
        }
    }
};

DB::ColumnPtr SparkFunctionNextDay::executeConst(const DB::ColumnsWithTypeAndName & arguments, const DB::DataTypePtr & result_type) const
{
    const auto * from_date_col = arguments[0].column.get();

    auto nested_result_type = DB::removeNullable(result_type);
    auto next_week_day = getDayOfWeek((*arguments[1].column)[0].safeGet<String>());
    if (next_week_day == -1) [[unlikely]]
        return result_type->createColumnConstWithDefaultValue(from_date_col->size());

    auto to_date_col = result_type->createColumn();
    to_date_col->reserve(from_date_col->size());
    DB::WhichDataType ty_which(nested_result_type);
    if (ty_which.isDate())
    {
        NextDayConstImpl<DB::DataTypeDate>::execute(
            *from_date_col, next_week_day, to_date_col.get(), NextDayConstTransformer{});
    }
    else if (ty_which.isDate32())
    {
        NextDayConstImpl<DB::DataTypeDate32>::execute(
            *from_date_col, next_week_day, to_date_col.get(), NextDayConstTransformer{});
    }
    else if (ty_which.isDateTime())
    {
        NextDayConstImpl<DB::DataTypeDateTime>::execute(
            *from_date_col, next_week_day, to_date_col.get(), NextDayConstTransformer{});
    }
    else if (ty_which.isDateTime64())
    {
        NextDayConstImpl<DB::DataTypeDateTime64>::execute(
            *from_date_col,
            next_week_day,
            to_date_col.get(),
            DB::TransformDateTime64<NextDayConstTransformer>{
                assert_cast<const DB::DataTypeDateTime64 *>(nested_result_type.get())->getScale()});
    }
    return std::move(to_date_col);
}

DB::ColumnPtr SparkFunctionNextDay::executeGeneral(const DB::ColumnsWithTypeAndName & arguments, const DB::DataTypePtr & result_type) const
{
    const auto * from_date_col = arguments[0].column.get();
    const auto * weekday_col = arguments[1].column.get();
    auto nested_result_type = DB::removeNullable(result_type);
    auto to_date_col = result_type->createColumn();
    to_date_col->reserve(from_date_col->size());
    DB::WhichDataType ty_which(nested_result_type);
    if (ty_which.isDate())
    {
        NextDayConstImpl<DB::DataTypeDate>::execute(
            *from_date_col, *weekday_col, to_date_col.get(), NextDayConstTransformer{});
    }
    else if (ty_which.isDate32())
    {
        NextDayConstImpl<DB::DataTypeDate32>::execute(
            *from_date_col, *weekday_col, to_date_col.get(), NextDayConstTransformer{});
    }
    else if (ty_which.isDateTime())
    {
        NextDayConstImpl<DB::DataTypeDateTime>::execute(
            *from_date_col, *weekday_col, to_date_col.get(), NextDayConstTransformer{});
    }
    else if (ty_which.isDateTime64())
    {
        NextDayConstImpl<DB::DataTypeDateTime64>::execute(
            *from_date_col,
            *weekday_col,
            to_date_col.get(),
            DB::TransformDateTime64<NextDayConstTransformer>{
                assert_cast<const DB::DataTypeDateTime64 *>(nested_result_type.get())->getScale()});
    }
    return std::move(to_date_col);
}

Int8 SparkFunctionNextDay::getDayOfWeek(const String & abbr)
{
    String lower_abbr = abbr;
    boost::to_lower(lower_abbr);
    // week mode must be 0
    static const std::unordered_map<String, Int8> abbr2day = {
        {"mo", 1},
        {"mon", 1},
        {"monday", 1},
        {"tu", 2},
        {"tue", 2},
        {"tuesday", 2},
        {"we", 3},
        {"wed", 3},
        {"wednesday", 3},
        {"th", 4},
        {"thu", 4},
        {"thursday", 4},
        {"fr", 5},
        {"fri", 5},
        {"friday", 5},
        {"sa", 6},
        {"sat", 6},
        {"saturday", 6},
        {"su", 7},
        {"sun", 7},
        {"sunday", 7}
    };
    auto it = abbr2day.find(lower_abbr);
    if (it != abbr2day.end()) [[likely]]
        return it->second;
    return -1;
}

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