#include "common/logger.hpp"

#include <cstdlib>

using namespace polygun::utils;

Logger* Logger::s_instance = nullptr;

Logger::Logger(bool output_to_file, bool enable_verbose) :
	m_output_to_file(output_to_file),
	m_enable_verbose(enable_verbose),
	m_output_file(nullptr)
{
	if(output_to_file) {
		m_output_file = fopen("log.txt", "w");
		if(!m_output_file) {
			m_output_to_file = false;
			LOG_ERROR("Failed to open 'log.txt' for writing, logging to file won't be enabled");
		}
	}
}

Logger::~Logger() {
	if(m_output_to_file)
		fclose(m_output_file);
}

void Logger::info(const char* file, size_t line, const char* fmt, ...) {
	va_list args;
	va_start(args, fmt);
	print_internal(stdout, "info", file, line, fmt, args);
	va_end(args);
	if(m_output_to_file) {
		va_start(args, fmt);
		print_internal(m_output_file, "info", file, line, fmt, args);
		va_end(args);
	}
}

void Logger::warning(const char* file, size_t line, const char* fmt, ...) {
	va_list args;
	va_start(args, fmt);
	print_internal(stdout, "warning", file, line, fmt, args);
	va_end(args);
	if(m_output_to_file) {
		va_start(args, fmt);
		print_internal(m_output_file, "warning", file, line, fmt, args);
		va_end(args);
	}
}

void Logger::error(const char* file, size_t line, const char* fmt, ...) {
	va_list args;
	va_start(args, fmt);
	print_internal(stderr, "error", file, line, fmt, args);
	va_end(args);
	if(m_output_to_file) {
		va_start(args, fmt);
		print_internal(m_output_file, "error", file, line, fmt, args);
		va_end(args);
	}
}

void Logger::fatal(const char* file, size_t line, const char* fmt, ...) {
	va_list args;
	va_start(args, fmt);
	print_internal(stderr, "fatal", file, line, fmt, args);
	va_end(args);
	if(m_output_to_file) {
		va_start(args, fmt);
		print_internal(m_output_file, "fatal", file, line, fmt, args);
		va_end(args);
	}
	exit(1);
}

void Logger::verbose(const char* file, size_t line, const char* fmt, ...) {
	if(!m_enable_verbose)
		return;
	va_list args;
	va_start(args, fmt);
	print_internal(stdout, "verbose", file, line, fmt, args);
	va_end(args);
	if(m_output_to_file) {
		va_start(args, fmt);
		print_internal(m_output_file, "verbose", file, line, fmt, args);
		va_end(args);
	}
}

void Logger::create(bool output_to_file, bool enable_verbose) {
	if(s_instance)
		cleanup();
	s_instance = new Logger(output_to_file, enable_verbose);
}

void Logger::print_internal(FILE* output, const char* mode, const char* file, size_t line, const char* fmt, va_list args) {
	fprintf(output, "[%s] %s:%zu: ", mode, file, line);
	vfprintf(output, fmt, args);
	fprintf(output, "\n");
	fflush(output);
}
