/*
 *  Copyright (C) 2006-2019, Thomas Maier-Komor
 *
 *  This is the source code of xjobs.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>	// for Solaris
#include <unistd.h>

#include "colortty.h"
#include "log.h"
#include "support.h"

verbose_t Verbose = Status;

extern void finalize(void);

static int Log = STDERR_FILENO;
static const char *LogName = 0;


void set_log(const char *fn)
{
	int newlog = open(fn,O_WRONLY|O_CREAT,0644);
	if (newlog == -1) {
		warn("unable to open logfile %s: %s\n",fn,strerror(errno));
		return;
	}
	int err = fcntl(newlog,F_SETFD,FD_CLOEXEC);
	assert(err != -1);
	if (Log != STDERR_FILENO)
		(void) close(Log);
	Log = newlog;
	LogName = fn;
}


void write_log(verbose_t v, const char *s, size_t l)
{
	if (Verbose < v)
		(void)Write(Log,s,l);
}


static char *init_pfx(char *b, size_t l, const char *p)
{
	size_t pl;
	if (p == 0) {
		p = TiNoAttr;
		pl = TiNoAttrL;
	} else
		pl = strlen(p);

	if (pl == 0)
		return b;
	assert(pl <= l);
	memcpy(b,p,pl+1);
	return b + pl;
}


void dbug(const char *msg, ...)
{
	if (Verbose < Debug)
		return;
	char buf[4096], *b = buf;
	if (Log == STDERR_FILENO)
		b = init_pfx(buf,sizeof(buf),PfxDebug);
	va_list val;
	va_start(val,msg);
	b += vsnprintf(b,sizeof(buf)-(b-buf),msg,val);
	va_end(val);
	if (b - buf > sizeof(buf)) {
		b = buf+sizeof(buf)-3;
		*b++ = '.';
		*b++ = '.';
		*b++ = '.';
	}
	Write(Log,buf,b-buf);
}


void info(const char *msg, ...)
{
	if (Verbose < Info)
		return;
	char buf[4096], *b = buf;
	if (Log == STDERR_FILENO)
		b = init_pfx(buf,sizeof(buf),PfxInfo);
	va_list val;
	va_start(val,msg);
	b += vsnprintf(b,sizeof(buf)-(b-buf),msg,val);
	va_end(val);
	if (b - buf > sizeof(buf)) {
		b = buf+sizeof(buf)-3;
		*b++ = '.';
		*b++ = '.';
		*b++ = '.';
	}
	Write(Log,buf,b-buf);
}


void status(const char *msg, ...)
{
	if (Verbose < Status)
		return;
	char buf[4096], *b = buf;
	va_list val;
	va_start(val,msg);
	b += vsnprintf(buf,sizeof(buf),msg,val);
	va_end(val);
	if (b - buf > sizeof(buf)) {
		b = buf+sizeof(buf)-3;
		*b++ = '.';
		*b++ = '.';
		*b++ = '.';
	}
	Write(STDOUT_FILENO,buf,b-buf);
}


void warn(const char *msg, ...)
{
	if (Verbose < Warning)
		return;
	char buf[4096], *b = buf;
	if (Log == STDERR_FILENO)
		b = init_pfx(buf,sizeof(buf),PfxWarn);
	va_list val;
	va_start(val,msg);
	b += vsnprintf(b,sizeof(buf)-(b-buf),msg,val);
	va_end(val);
	if (b - buf > sizeof(buf)) {
		b = buf+sizeof(buf)-3;
		*b++ = '.';
		*b++ = '.';
		*b++ = '.';
	}
	Write(Log,buf,b-buf);
}


void error(const char *msg, ...)
{
	if (Verbose >= Error) {
		char buf[4096], *b = buf;
		if (Log == STDERR_FILENO)
			b = init_pfx(buf,sizeof(buf),PfxError);
		va_list val;
		va_start(val,msg);
		b += vsnprintf(b,sizeof(buf)-(b-buf),msg,val);
		va_end(val);
		if (b - buf > sizeof(buf)) {
			b = buf+sizeof(buf)-3;
			*b++ = '.';
			*b++ = '.';
			*b++ = '.';
		}
		Write(Log,buf,b-buf);
	}
	finalize();
}


