// 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 "vec/exprs/function_context.h"

#include <iostream>
#include <utility>

// Be careful what this includes since this needs to be linked into UDF's
// binary. For example, it would be unfortunate if they had a random dependency
// on libhdfs.
#include "common/cast_set.h"
#include "runtime/runtime_state.h"
#include "runtime/types.h"
#include "vec/common/string_ref.h"
#include "vec/data_types/data_type.h"

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

static const int MAX_WARNINGS = 1000;

std::unique_ptr<doris::FunctionContext> FunctionContext::create_context(
        RuntimeState* state, const vectorized::DataTypePtr& return_type,
        const std::vector<vectorized::DataTypePtr>& arg_types) {
    auto ctx = std::unique_ptr<doris::FunctionContext>(new doris::FunctionContext());
    ctx->_state = state;
    ctx->_return_type = return_type;
    ctx->_arg_types = arg_types;
    ctx->_num_warnings = 0;
    ctx->_thread_local_fn_state = nullptr;
    ctx->_fragment_local_fn_state = nullptr;
    return ctx;
}

void FunctionContext::set_constant_cols(
        const std::vector<std::shared_ptr<doris::ColumnPtrWrapper>>& constant_cols) {
    _constant_cols = constant_cols;
}

std::unique_ptr<FunctionContext> FunctionContext::clone() {
    auto new_context = create_context(_state, _return_type, _arg_types);
    new_context->_constant_cols = _constant_cols;
    new_context->_fragment_local_fn_state = _fragment_local_fn_state;
    new_context->_check_overflow_for_decimal = _check_overflow_for_decimal;
    new_context->_enable_strict_mode = _enable_strict_mode;
    new_context->_string_as_jsonb_string = _string_as_jsonb_string;
    new_context->_jsonb_string_as_string = _jsonb_string_as_string;
    return new_context;
}

void FunctionContext::set_function_state(FunctionStateScope scope, std::shared_ptr<void> ptr) {
    switch (scope) {
    case THREAD_LOCAL:
        _thread_local_fn_state = std::move(ptr);
        break;
    case FRAGMENT_LOCAL:
        _fragment_local_fn_state = std::move(ptr);
        break;
    default:
        std::stringstream ss;
        ss << "Unknown FunctionStateScope: " << scope;
        set_error(ss.str().c_str());
    }
}

void FunctionContext::set_error(const char* error_msg) {
    if (_error_msg.empty()) {
        _error_msg = error_msg;
        std::stringstream ss;
        ss << "UDF ERROR: " << error_msg;

        if (_state != nullptr) {
            _state->cancel(Status::InternalError(ss.str()));
        }
    }
}

bool FunctionContext::add_warning(const char* warning_msg) {
    if (_num_warnings++ >= MAX_WARNINGS) {
        return false;
    }

    std::stringstream ss;
    ss << "UDF WARNING: " << warning_msg;

    if (_state != nullptr) {
        return _state->log_error(ss.str());
    } else {
        std::cerr << ss.str() << std::endl;
        return true;
    }
}

const vectorized::DataTypePtr FunctionContext::get_arg_type(int arg_idx) const {
    if (arg_idx < 0 || arg_idx >= _arg_types.size()) {
        return nullptr;
    }
    return _arg_types[arg_idx];
}

bool FunctionContext::is_col_constant(int i) const {
    if (i < 0 || i >= _constant_cols.size()) {
        return false;
    }
    return _constant_cols[i] != nullptr;
}

doris::ColumnPtrWrapper* FunctionContext::get_constant_col(int i) const {
    if (i < 0 || i >= _constant_cols.size()) {
        return nullptr;
    }
    return _constant_cols[i].get();
}

int FunctionContext::get_num_args() const {
    return cast_set<int>(_arg_types.size());
}

const vectorized::DataTypePtr FunctionContext::get_return_type() const {
    return _return_type;
}

void* FunctionContext::get_function_state(FunctionStateScope scope) const {
    switch (scope) {
    case THREAD_LOCAL:
        return _thread_local_fn_state.get();
    case FRAGMENT_LOCAL:
        return _fragment_local_fn_state.get();
    default:
        // TODO: signal error somehow
        return nullptr;
    }
}

StringRef FunctionContext::create_temp_string_val(int64_t len) {
    _string_result.resize(len);
    return StringRef((uint8_t*)_string_result.c_str(), len);
}

#include "common/compile_check_end.h"
} // namespace doris
