/***************************************************************************
 *   Copyright (C) 2004 by EVER Sp. z o.o.                                 *
 *                                                                         *
 *   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, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#define _XOPEN_SOURCE
#include <time.h>
#include "clog.h"

CLog::CLog()
{
	bbuffered=bsyslog=bprvlog=bread=false;
	data_length = 0;
	data_buff = NULL;
	fprvlog=NULL;
}

CLog::~CLog()
{
	if (bbuffered)
		free(data_buff);
	if (fprvlog!=NULL)
		fclose(fprvlog);
	if (bsyslog)
		closelog();
}

int CLog::open(char *fp, char *ln)
{
	if (bread)
		return LOG_FAILURE;
	bread = false;
	if (ln!=NULL) {
		openlog(logname, LOG_PID|LOG_NDELAY, LOG_DAEMON);
		bsyslog=true;
	}
	if (fp!=NULL) {
		if (openprvlog(fp)!=LOG_SUCCESS)
			return LOG_FAILURE;
		bprvlog=true;
	}
	return LOG_SUCCESS;
}

int CLog::openprvlog(char *fp)
{
	if (fp==NULL || bread)
		return LOG_FAILURE;
	bread = false;
	fprvlog=fopen(fp, "a+");
	if (fprvlog==NULL)
		return LOG_FAILURE;
	return LOG_SUCCESS;
}

int CLog::open_read(char *fp)
{
	if (fp==NULL)
		return LOG_FAILURE;
	bread = true;
	fprvlog=fopen(fp, "r");
	if (fprvlog==NULL)
		return LOG_FAILURE;
	bprvlog = true;
	return LOG_SUCCESS;
}

int CLog::open_read_buff(char *fp)
{
	if (fp==NULL)
		return LOG_FAILURE;
	bread = bbuffered = true;
	fprvlog=fopen(fp, "r");
	if (fprvlog==NULL)
		return LOG_FAILURE;
	bprvlog = true;
	
	fseek(fprvlog, 0L, SEEK_END);
	data_length = ftell(fprvlog);
	data_buff = (char*)malloc(data_length);
	if (!data_buff) {
		fclose(fprvlog);
		return LOG_FAILURE;
	}
	memset(data_buff, 0, data_length);
	fseek(fprvlog, 0, SEEK_SET);
	data_length = fread(data_buff, sizeof(char), data_length, fprvlog);
	
	return LOG_SUCCESS;
}

int CLog::new_msg(msgtype t, char *content, ...)
{
	if (bsyslog) {
		va_list ap;
		va_start(ap, content);
		vsyslog((int)t, content, ap);
		va_end(ap);
	}
	if (bprvlog) {
		if (fprvlog==NULL)
			return LOG_FAILURE;
		time_t tm;
		time(&tm);
		const int stimelen=128;
		char *stime=new char[stimelen];
		if (stime!=NULL) {
			strftime(stime, sizeof(char)*stimelen, "%d-%m-%Y %T ", localtime(&tm));
			fprintf(fprvlog, stime);
			delete [] stime;
		}
		fprintf(fprvlog, "|%d| ", t);
		va_list ap;
		va_start(ap, content);
		vfprintf(fprvlog, content, ap);
		va_end(ap);
		fprintf(fprvlog, "\n");
		fflush(fprvlog);
	}
	return LOG_SUCCESS;
}

int CLog::new_syslog_msg(msgtype t, char *content, ...)
{
	if (bsyslog) {
		va_list ap;
		va_start(ap, content);
		vsyslog((int)t, content, ap);
		va_end(ap);
		return LOG_SUCCESS;
	} else
		return LOG_FAILURE;
}


int CLog::read_msg(struct tm *evtime, msgtype *t, char *buff, int buffsize, long *line)
{
	long datalen = 0;
	char *data, *datatok;
	
	if (bprvlog) {
		if (fprvlog==NULL || buff==NULL || buffsize<=0 || line==NULL)
			return LOG_FAILURE;
		memset(buff, 0, buffsize);
		
		if (!bbuffered) {
			fseek(fprvlog, 0L, SEEK_END);
			datalen = ftell(fprvlog);
			data = (char*)calloc(datalen, sizeof(char));
			if (!data)
				return LOG_FAILURE;
			memset(data, 0, datalen);
			fseek(fprvlog, 0, SEEK_SET);
			datalen = fread(data, sizeof(char), datalen, fprvlog);
			if (datalen > 0) {
				datatok = (char*)calloc(buffsize, sizeof(char));
				if (datatok!=NULL) {
					char *tok = token(data, datatok, '\n', *line);
					// reparse token into subtokens
					if (tok != NULL && tok != '\0') {
						char *subtok = (char*)calloc(strlen(datatok), sizeof(char));
						if (subtok!=NULL) {
							char *ttok = token(tok, subtok, '|', 0);
							if (ttok!=NULL)
								strptime(ttok, "%d-%m-%Y %T", evtime);
							ttok = token(tok, subtok, '|', 1);
							if (ttok!=NULL)
								*t = (msgtype)msgtype(atoi(ttok));
							ttok = token(tok, subtok, '|', 2);
							if (ttok!=NULL) {
								if (strlen(ttok)>(size_t)buffsize)
									memcpy(buff, ttok, buffsize);
								else
									memcpy(buff, ttok, strlen(ttok));
							}
							free(subtok);
						}
					}
					free(datatok);
				}
			}
			free(data);
		} else {
			if (data_length > 0) {
				datatok = (char*)calloc(buffsize, sizeof(char));
				if (datatok!=NULL) {
					char *tok = token(data_buff, datatok, '\n', *line);
					// reparse token into subtokens
					if (tok != NULL && tok != '\0') {
						char *subtok = (char*)calloc(strlen(datatok), sizeof(char));
						if (subtok!=NULL) {
							char *ttok = token(tok, subtok, '|', 0);
							if (ttok!=NULL)
								strptime(ttok, "%d-%m-%Y %T", evtime);
							ttok = token(tok, subtok, '|', 1);
							if (ttok!=NULL)
								*t = (msgtype)msgtype(atoi(ttok));
							ttok = token(tok, subtok, '|', 2);
							if (ttok!=NULL)
								if (strlen(ttok)>(size_t)buffsize)
									memcpy(buff, ttok, buffsize);
								else
									memcpy(buff, ttok, strlen(ttok));
							free(subtok);
						}
					}
					free(datatok);
				}
			}
		}
	}
	return LOG_SUCCESS;
}

char* CLog::token(char *src, char *res, char delim)
{
	int index = 0, idxres = 0;
	
	if (src==NULL || res==NULL)
		return NULL;

	while (src[index]!='\0') {
		if (src[index]!=delim) {
			res[idxres++]=src[index];
		} else {
			res[idxres++]='\0';
			return res;
		}
		index++;
	}
	res[idxres]='\0';
	return res;
}

char* CLog::token(char *src, char *res, char delim, int tokidx)
{
	int index = 0, idxres = 0, cnt = 0;

	if (src==NULL || res==NULL)
		return NULL;

	while (src[index]!='\0') {
		if (cnt==tokidx) {
			if (src[index]!=delim) {
				res[idxres]=src[index];
				idxres++;
			} else {
				res[idxres]='\0';
				return res;
			}
		} else {
			if (src[index]==delim) {
				cnt++;
			}
		}
		index++;
	}
	res[idxres]='\0';
	return res;
}

int CLog::get_linecount(long *lines)
{
	unsigned long datalen = 0, cnt = 0;
	char *data;
	if (bprvlog) {
		if (fprvlog==NULL || lines==NULL)
			return LOG_FAILURE;
		if (!bbuffered) {
			fseek(fprvlog, 0L, SEEK_END);
			datalen = (unsigned long)ftell(fprvlog);
			if (datalen<=0)
				return LOG_FAILURE;
			data = (char*)malloc(datalen);
			if (!data)
				return LOG_FAILURE;
			memset(data, 0, datalen);
			fseek(fprvlog, 0, SEEK_SET);
			datalen = fread(data, sizeof(char), datalen, fprvlog);
			if (datalen > 0) {
				cnt = 0;
				for (unsigned int l=0; l<(unsigned int)datalen; l++) {
					if (data[l]=='\n')
						cnt++;
				}
			} else {
				free(data);
				return LOG_FAILURE;
			}
			free(data);
		} else {
			if (data_length > 0) {
				cnt = 0;
				for (unsigned int l=0; l<(unsigned int)data_length; l++) {
					if (data_buff[l]=='\n')
						cnt++;
				}
			} else
				return LOG_FAILURE;
		}
	} else
		return LOG_FAILURE;
	*lines = (long)cnt;
	return LOG_SUCCESS;
}

