/*
 * 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 <DataTypes/DataTypeString.h>
#include <Parser/FunctionParser.h>
#include <Common/DateLUTImpl.h>

namespace DB
{

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


namespace local_engine
{

class FunctionParserTimestampAdd : public FunctionParser
{
public:
    explicit FunctionParserTimestampAdd(ParserContextPtr parser_context_) : FunctionParser(parser_context_) { }
    ~FunctionParserTimestampAdd() override = default;

    static constexpr auto name = "timestampadd";

    String getName() const override { return name; }
    String getCHFunctionName(const substrait::Expression_ScalarFunction &) const override { return "timestamp_add"; }

    const DB::ActionsDAG::Node * parse(const substrait::Expression_ScalarFunction & substrait_func, DB::ActionsDAG & actions_dag) const override
    {
        auto parsed_args = parseFunctionArguments(substrait_func, actions_dag);
        if (parsed_args.size() < 3)
            throw DB::Exception(DB::ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH, "Function {} requires at least three arguments", getName());

        const auto & unit_field = substrait_func.arguments().at(0);
        if (!unit_field.value().has_literal() || !unit_field.value().literal().has_string())
            throw DB::Exception(
                DB::ErrorCodes::BAD_ARGUMENTS, "Unsupported unit argument, should be a string literal, but: {}", unit_field.DebugString());

        String timezone;
        if (parsed_args.size() == 4)
        {
            const auto & timezone_field = substrait_func.arguments().at(3);
            if (!timezone_field.value().has_literal() || !timezone_field.value().literal().has_string())
            throw DB::Exception(
                DB::ErrorCodes::BAD_ARGUMENTS,
                "Unsupported timezone_field argument, should be a string literal, but: {}",
                timezone_field.DebugString());
            timezone = timezone_field.value().literal().string();
        }

        const auto & unit = Poco::toUpper(unit_field.value().literal().string());

        std::string ch_function_name;
        if (unit == "MICROSECOND")
            ch_function_name = "addMicroseconds";
        else if (unit == "MILLISECOND")
            ch_function_name = "addMilliseconds";
        else if (unit == "SECOND")
            ch_function_name = "addSeconds";
        else if (unit == "MINUTE")
            ch_function_name = "addMinutes";
        else if (unit == "HOUR")
            ch_function_name = "addHours";
        else if (unit == "DAY" || unit == "DAYOFYEAR")
            ch_function_name = "addDays";
        else if (unit == "WEEK")
            ch_function_name = "addWeeks";
        else if (unit == "MONTH")
            ch_function_name = "addMonths";
        else if (unit == "QUARTER")
            ch_function_name = "addQuarters";
        else if (unit == "YEAR")
            ch_function_name = "addYears";
        else
            throw DB::Exception(DB::ErrorCodes::BAD_ARGUMENTS, "Unsupported unit argument: {}", unit);

        if (timezone.empty())
            timezone = DateLUT::instance().getTimeZone();

        const auto * time_zone_node = addColumnToActionsDAG(actions_dag, std::make_shared<DB::DataTypeString>(), timezone);
        const DB::ActionsDAG::Node * result_node
            = toFunctionNode(actions_dag, ch_function_name, {parsed_args[2], parsed_args[1], time_zone_node});

        return convertNodeTypeIfNeeded(substrait_func, result_node, actions_dag);
    }
};
static FunctionParserRegister<FunctionParserTimestampAdd> register_timestamp_add;
}
