// 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 "exprs/aggregate/aggregate_function_map.h"

#include "core/call_on_type_index.h"
#include "exprs/aggregate/helpers.h"

namespace doris {
#include "common/compile_check_begin.h"

template <PrimitiveType K>
AggregateFunctionPtr create_agg_function_map_agg(const DataTypes& argument_types,
                                                 const bool result_is_nullable,
                                                 const AggregateFunctionAttr& attr) {
    return creator_without_type::create_ignore_nullable<
            AggregateFunctionMapAgg<AggregateFunctionMapAggData<K>, K>>(argument_types,
                                                                        result_is_nullable, attr);
}

AggregateFunctionPtr create_aggregate_function_map_agg(const std::string& name,
                                                       const DataTypes& argument_types,
                                                       const DataTypePtr& result_type,
                                                       const bool result_is_nullable,
                                                       const AggregateFunctionAttr& attr) {
    AggregateFunctionPtr agg_fn;
    auto call = [&](const auto& type) -> bool {
        using DispatcType = std::decay_t<decltype(type)>;
        agg_fn = create_agg_function_map_agg<DispatcType::PType>(argument_types, result_is_nullable,
                                                                 attr);
        return true;
    };

    if (!dispatch_switch_all(argument_types[0]->get_primitive_type(), call)) {
        LOG(WARNING) << fmt::format("unsupported input type {} for aggregate function {}",
                                    argument_types[0]->get_name(), name);
        return nullptr;
    }
    return agg_fn;
}

void register_aggregate_function_map_agg(AggregateFunctionSimpleFactory& factory) {
    factory.register_function_both("map_agg_v1", create_aggregate_function_map_agg);
    factory.register_alias("map_agg_v1", "map_agg");
}

} // namespace doris