#ifndef TARIFF_LOG_INCLUDED_H
#define TARIFF_LOG_INCLUDED_H

#include <string>
#include <iostream>

#define DBG_LEVEL_DEBUG     0
#define DBG_LEVEL_INFO      1
#define DBG_LEVEL_WARN      2
#define DBG_LEVEL_CRITICAL  3
#define DBG_LEVEL_ERROR     4
#define DBG_LEVEL_FATAL     5

void setDebugLevel(int level);
int getDebugLevel();

static void print() {
    std::cerr << "\n";
    if (getDebugLevel() == DBG_LEVEL_FATAL) {
        exit(-1);
    }
} // termination version

template<typename Arg1, typename... Args>
static void print(const Arg1& arg1, Args&&... args) {
    std::cerr << arg1;
    print(args...);
}

template<typename Arg1, typename... Args>
static void LOG_DEBUG(const Arg1& arg1, Args&&... args) {
    if (getDebugLevel() <= DBG_LEVEL_DEBUG) {
        std::cerr << "DEBUG " << arg1;
        print(args...);
    }
}

template<typename Arg1, typename... Args>
static void LOG_INFO(const Arg1& arg1, Args&&... args) {
    if (getDebugLevel() <= DBG_LEVEL_INFO) {
        std::cerr << "INFO " << arg1;
        print(args...);
    }
}

template<typename Arg1, typename... Args>
static void LOG_WARNING(const Arg1& arg1, const Args&&... args) {
    if (getDebugLevel() <= DBG_LEVEL_WARN) {
        std::cerr << "WARNING " << arg1;
        print(args...);
    }
}

template<typename Arg1, typename... Args>
static void LOG_CRITICAL(const Arg1& arg1, const Args&&... args) {
    if (getDebugLevel() <= DBG_LEVEL_CRITICAL) {
        std::cerr << "CRITICAL " << arg1;
        print(args...);
    }
}

template<typename Arg1, typename... Args>
static void LOG_ERROR(const Arg1& arg1, const Args&&... args) {
    if (getDebugLevel() <= DBG_LEVEL_ERROR) {
        std::cerr << "ERROR " << arg1;
        print(args...);
    }
}

template<typename Arg1, typename... Args>
static void LOG_FATAL(const Arg1& arg1, const Args&&... args) {
    if (getDebugLevel() <= DBG_LEVEL_FATAL) {
        std::cerr << "FATAL " << arg1;
        print(args...);
    }
}

#endif //  TARIFF_LOG_INCLUDED_H