
#include <stdarg.h>
#include <stdio.h>
#include <sys/time.h>
#include <unistd.h>

#include "Version.h"
#include "Config.h"
#include "Log.h"

Log::Log()
{
	pthread_mutex_init(&mutex, NULL);
	active = 0;
	lastLine[0] = lastVerboseLine[0] = 0;
	counter = vCounter = 0;
}

void Log::debug(const char *tag, const char *format, ...)
{
	if (strstr(config.getDebug(), tag) != NULL)
	{
		char str[sizeof lastVerboseLine];
		va_list ap;
		va_start(ap, format);
		vsnprintf(str, sizeof str, format, ap);
		va_end(ap);
		putv("%s: %s", tag, str);
	}
}

void Log::put(const char *format, ...)
{
	if (!active || !config.getLogRequests())
		return;

	char line[sizeof lastLine];
	va_list ap;
	va_start(ap, format);
	vsnprintf(line, sizeof line, format, ap);
	va_end(ap);

	writeLine(line, file, lastLine, counter);
}

void Log::putv(const char *format, ...)
{
	if (!active || !config.getLogVerbose())
		return;

	char line[sizeof lastVerboseLine];
	va_list ap;
	va_start(ap, format);
	vsnprintf(line, sizeof line, format, ap);
	va_end(ap);

	writeLine(line, vFile, lastVerboseLine, vCounter);
}

void Log::start(int putvToStdOut)
{
	char fileName[4*1024];
	sprintf(fileName, "%s/%s.log",
		config.getLogDir(), version);
	file = fopen(fileName, "a");
	if (file == NULL)
		file = stdout;

	if (putvToStdOut)
		vFile = stdout;
	else
	{
		sprintf(fileName, "%s/%s.vlog",
			config.getLogDir(), version);
		vFile = fopen(fileName, "a");
		if (vFile == NULL)
			vFile = stdout;
	}

	active = 1;

	time_t t;
	time(&t);
	log.put("*** %s %s, %s", product, version, ctime(&t));
	log.put("uid = %d, euid = %d, gid = %d, egid = %d",
		getuid(), geteuid(), getgid(), getegid());
}

void Log::writeLine(char *line, FILE *aFile,
		char *lastLine, int &counter)
{
	int l = strlen(line);
	if (l > 0 && line[l-1] == '\n')
		line[l-1] = 0;

	pthread_mutex_lock(&mutex);
	if (strcmp(line, lastLine) == 0)
		counter++;
	else
	{
		if (counter > 0)
			fprintf(aFile, "\trepeated %d times\n", counter);
		counter = 0;
		fprintf(aFile, "%d: %s\n", getpid(), line);
	}
	strcpy(lastLine, line);
	pthread_mutex_unlock(&mutex);

	fflush(aFile);

	if (aFile == file && file != vFile)
		writeLine(line, vFile, lastVerboseLine, vCounter);
}
