#pragma once

#include "bmcweb_config.h"

#include <algorithm>
#include <array>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <filesystem>
#include <iostream>
#include <sstream>
#include <string>
#include <string_view>

namespace crow
{
enum class LogLevel
{
    Disabled = 0,
    Debug,
    Info,
    Warning,
    Error,
    Critical,
};

// Mapping of the external loglvl name to internal loglvl
constexpr std::array<std::pair<std::string_view, crow::LogLevel>, 7>
    mapLogLevelFromName{{{"disabled", crow::LogLevel::Disabled},
                         {"enabled", crow::LogLevel::Debug},
                         {"debug", crow::LogLevel::Debug},
                         {"info", crow::LogLevel::Info},
                         {"warning", crow::LogLevel::Warning},
                         {"error", crow::LogLevel::Error},
                         {"critical", crow::LogLevel::Critical}}};

constexpr crow::LogLevel getLogLevelFromName(std::string_view name)
{
    const auto* iter =
        std::find_if(begin(mapLogLevelFromName), end(mapLogLevelFromName),
                     [&name](const auto& v) { return v.first == name; });
    if (iter != end(mapLogLevelFromName))
    {
        return iter->second;
    }
    return crow::LogLevel::Disabled;
}

// configured bmcweb LogLevel
constexpr crow::LogLevel bmcwebCurrentLoggingLevel =
    getLogLevelFromName(bmcwebLoggingLevel);

class Logger
{
  private:
    //
    static std::string timestamp()
    {
        std::string date;
        date.resize(32, '\0');
        time_t t = time(nullptr);

        tm myTm{};

        gmtime_r(&t, &myTm);

        size_t sz = strftime(date.data(), date.size(), "%Y-%m-%d %H:%M:%S",
                             &myTm);
        date.resize(sz);
        return date;
    }

  public:
    Logger([[maybe_unused]] const std::string& prefix,
           [[maybe_unused]] const std::string& filename,
           [[maybe_unused]] const size_t line)
    {
        stringstream << "(" << timestamp() << ") [" << prefix << " "
                     << std::filesystem::path(filename).filename() << ":"
                     << line << "] ";
    }
    ~Logger()
    {
        stringstream << std::endl;
        std::cerr << stringstream.str();
    }

    Logger(const Logger&) = delete;
    Logger(Logger&&) = delete;
    Logger& operator=(const Logger&) = delete;
    Logger& operator=(const Logger&&) = delete;

    //
    template <typename T>
    Logger& operator<<([[maybe_unused]] const T& value)
    {
        // Somewhere in the code we're implicitly casting an array to a
        // pointer in logging code. It's non-trivial to find,
        // so disable the check here for now
        // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
        stringstream << value;
        return *this;
    }

    constexpr static LogLevel getCurrentLogLevel()
    {
        return bmcwebCurrentLoggingLevel;
    }

    constexpr static bool isLoggingEnabled()
    {
        return getCurrentLogLevel() >= crow::LogLevel::Debug;
    }

    constexpr static bool checkLoggingLevel(const LogLevel level)
    {
        return isLoggingEnabled() && (getCurrentLogLevel() <= level);
    }

  private:
    //
    std::ostringstream stringstream;
};
} // namespace crow

// Disable clang-tidy warnings about unused macros.
// NOLINTBEGIN(cppcoreguidelines-macro-usage, clang-diagnostic-unused-macros)

// The logging functions currently use macros.  Now that we have c++20, ideally
// they'd use source_location with fixed functions, but for the moment, disable
// the check.
#define BMCWEB_LOG_CRITICAL                                                    \
    if constexpr (crow::Logger::checkLoggingLevel(crow::LogLevel::Critical))   \
    crow::Logger("CRITICAL", __FILE__, __LINE__)

#define BMCWEB_LOG_ERROR                                                       \
    if constexpr (crow::Logger::checkLoggingLevel(crow::LogLevel::Error))      \
    crow::Logger("ERROR", __FILE__, __LINE__)

#define BMCWEB_LOG_WARNING                                                     \
    if constexpr (crow::Logger::checkLoggingLevel(crow::LogLevel::Warning))    \
    crow::Logger("WARNING", __FILE__, __LINE__)

#define BMCWEB_LOG_INFO                                                        \
    if constexpr (crow::Logger::checkLoggingLevel(crow::LogLevel::Info))       \
    crow::Logger("INFO", __FILE__, __LINE__)

#define BMCWEB_LOG_DEBUG                                                       \
    if constexpr (crow::Logger::checkLoggingLevel(crow::LogLevel::Debug))      \
    crow::Logger("DEBUG", __FILE__, __LINE__)

// NOLINTEND(cppcoreguidelines-macro-usage, clang-diagnostic-unused-macros)
