#pragma once

#include <iostream>
#include <source_location>
#include <sstream>
#include <string>
#include <variant>
#include <vector>

#include "error.h"
#include "locator.h"
// #include "source.h"
#include "katom_list.h"

extern int verbose_level;
extern bool show_verbose_location;

std::ostream& operator<<(std::ostream& os, const std::variant<bool,int,float,std::string,const char*,Locator>& arg);

void display_location(int log_level, std::source_location location);

namespace K {
template <typename... Ts>
struct log
{
    log(int log_level, Ts&&... ts, const std::source_location& location = std::source_location::current()) {
        if (verbose_level >= log_level) {
            display_location(log_level, location);
            // stderr, always.  Logging is category 1 (see the output policy in
            // CLAUDE.md); stdout belongs to the command's RESULT, and for
            // ktext that result is a document a user may pipe.  Writing a log
            // line to stdout put it inside the document.
            if (verbose_level > 1 && sizeof...(ts) > 0) {
                std::cerr << ": ";
            } else if (verbose_level == 1) {
                std::cerr << command_name << ": ";
            }
            if (log_level > 0) {
                ((std::cerr << std::forward<Ts>(ts) << " "), ...);
                std::cerr << '\n';
            }
        }
    }
};

template <typename... Ts>
log(int log_level, Ts&&...) -> log<Ts...>;
}

/*
void log(int level = 3, const std::source_location location = std::source_location::current());

template<typename T, typename... Args>
void log(Args... args, int level = 3, const std::source_location location = std::source_location::current());
*/

/*
void log(std::vector<std::variant<bool,int,float,std::string,const char*,Locator,Source>> args={}, int level=3,
         const std::source_location location
         = std::source_location::current());

void xlog(std::vector<std::variant<bool,int,float,std::string,const char*,Locator,Source>> args={}, int verbose_override=1,
         const std::source_location location
         = std::source_location::current());
*/

void warning(const std::string& message, const Locator& loc);
