// 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 "util/debug_util.h"

#include <bvar/bvar.h>
#include <bvar/multi_dimension.h>
#include <gen_cpp/HeartbeatService_types.h>
#include <gen_cpp/PlanNodes_types.h>
#include <gflags/gflags.h>
#include <stdint.h>

#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <list>
#include <map>
#include <sstream> // IWYU pragma: keep
#include <string>
#include <utility>

#include "common/check.h"
#include "common/config.h"
#include "common/version_internal.h"
#include "fmt/core.h"
#include "util/uid_util.h"

namespace doris {

std::string print_plan_node_type(const TPlanNodeType::type& type) {
    std::map<int, const char*>::const_iterator i;
    i = _TPlanNodeType_VALUES_TO_NAMES.find(type);

    if (i != _TPlanNodeType_VALUES_TO_NAMES.end()) {
        return i->second;
    }

    return "Invalid plan node type";
}

std::string get_build_version(bool compact) {
    std::stringstream ss;
    // clang-format off
    ss << version::doris_build_version()
#if defined(__x86_64__) || defined(_M_X64)
#ifdef __AVX2__
       << "(AVX2)"
#else
       << "(SSE4.2)"
#endif
#elif defined(__aarch64__)
       << "(AArch64)"
#endif
#ifdef NDEBUG
       << " RELEASE"
#else
       << " DEBUG"
#if defined(ADDRESS_SANITIZER)
       << " with ASAN"
#elif defined(LEAK_SANITIZER)
       << " with LSAN"
#elif defined(THREAD_SANITIZER)
       << " with TSAN"
#elif defined(UNDEFINED_BEHAVIOR_SANITIZER)
       << " with UBSAN"
#elif defined(MEMORY_SANITIZER)
       << " with MSAN"
#elif defined(BLACKLIST_SANITIZER)
       << " with BLSAN"
#endif
#endif
       << (version::doris_feature_list().empty() ? "" : " features: " + version::doris_feature_list())
       << " (build " << version::doris_build_hash() << ")";
    // clang-format on

    if (!compact) {
        ss << std::endl
           << "Built on " << version::doris_build_time() << " by " << version::doris_build_info();
    }

    return ss.str();
}

std::string get_short_version() {
    static std::string short_version(std::string(version::doris_build_version()) + "-" +
                                     version::doris_build_short_hash());
    return short_version;
}

std::string get_version_string(bool compact) {
    std::stringstream ss;
    ss << " version " << get_build_version(compact);
    return ss.str();
}

std::string hexdump(const char* buf, int len) {
    std::stringstream ss;
    ss << std::hex << std::uppercase;
    for (int i = 0; i < len; ++i) {
        ss << std::setfill('0') << std::setw(2) << ((uint16_t)buf[i] & 0xff);
    }
    return ss.str();
}

namespace {

uint64_t get_be_version_metric_value() {
    std::stringstream ss;
    ss << version::doris_build_version_major() << 0 << version::doris_build_version_minor() << 0
       << version::doris_build_version_patch();
    if (version::doris_build_version_hotfix() > 0) {
        ss << 0 << version::doris_build_version_hotfix();
    }
    return std::strtoul(ss.str().c_str(), nullptr, 10);
}

} // namespace

void init_be_version_metrics() {
    // MultiDimension metrics are omitted from /brpc_metrics while this brpc flag is 0.
    DORIS_CHECK(
            !google::SetCommandLineOption("bvar_max_dump_multi_dimension_metric_number",
                                          config::bvar_max_dump_multi_dimension_metric_num.c_str())
                     .empty());

    static const bool initialized = [] {
        static bvar::MultiDimension<bvar::Status<uint64_t>> metrics(
                "doris_be_version", {"version", "major", "minor", "patch", "hotfix", "short_hash"});
        auto* metric = metrics.get_stats(
                std::list<std::string> {version::doris_build_version(),
                                        std::to_string(version::doris_build_version_major()),
                                        std::to_string(version::doris_build_version_minor()),
                                        std::to_string(version::doris_build_version_patch()),
                                        std::to_string(version::doris_build_version_hotfix()),
                                        version::doris_build_short_hash()});
        DORIS_CHECK(metric != nullptr);
        metric->set_value(get_be_version_metric_value());
        return true;
    }();
    static_cast<void>(initialized);
}

std::string PrintThriftNetworkAddress(const TNetworkAddress& add) {
    std::stringstream ss;
    add.printTo(ss);
    return ss.str();
}

std::string PrintFrontendInfos(const std::vector<TFrontendInfo>& fe_infos) {
    std::stringstream ss;
    const size_t count = fe_infos.size();

    for (int i = 0; i < count; ++i) {
        fe_infos[i].printTo(ss);
        ss << ' ';
    }

    return ss.str();
}

std::string PrintFrontendInfo(const TFrontendInfo& fe_info) {
    std::stringstream ss;
    fe_info.printTo(ss);
    return ss.str();
}

std::string PrintInstanceStandardInfo(const TUniqueId& qid, const TUniqueId& iid) {
    return fmt::format("{}|{}", print_id(qid), print_id(iid));
}

} // namespace doris
