/* Automagical Data Logger code V1.01 19/8/04
   Copyright 2008 Jeffrey Lee
   This file is part of WOUM.
   WOUM 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 3 of the License, or
   (at your option) any later version.
   WOUM 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 WOUM.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef _AMDL_C
#define _AMDL_C

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>

#include "amdl.h"

static FILE *log = 0;
static int on = 0;
static int col = 0;

typedef struct _amdl_line {
	struct _amdl_line *next; /* Next line in this column */
	char txt[0]; /* Vari-size text */
} amdl_line;

typedef struct {
	amdl_line *top,*bottom; /* Top & bottom lines in the column */
	int nlines; /* Number of lines */
} amdl_col;

static amdl_col cols[AMDL_COLS];

static char tbuf[1024];

static void flush_line(int c)
{
	amdl_line *l;
	if (cols[c].top)
	{
		l = cols[c].top;
		cols[c].top = l->next;
		if (l->next == 0)
			cols[c].bottom = 0;
		cols[c].nlines--;
		free(l);
	}
}

static void flush_cols(int c)
{
	while (cols[c].top)
		flush_line(c);
}

static void add_col(int c,char *txt)
{
	amdl_line *a;
	a = malloc(sizeof(amdl_line)+strlen(txt)+1);
	a->next = 0;
	strcpy(a->txt,txt);
	if (cols[c].bottom)
		cols[c].bottom->next = a;
	else
		cols[c].top = a;
	cols[c].bottom = a;
	cols[c].nlines++;
	col = c;
}

void amdl_on()
{
	int i;
	if (on)
		return;
	on = 1;
	for (i=0;i<AMDL_COLS;i++)
		flush_cols(i);
	if (log)
		return;
	log = fopen("amdl_log","w");
}

void amdl_off(int c)
{
	if (!on)
		return;
	on = 0;
	if (c)
	{
		fclose(log);
		log = 0;
	}
}

void amdl_abs(int column,char *format,...)
{
	va_list a;
	va_start(a,format);
	if (!on)
		return;
	vsprintf(tbuf,format,a);
	add_col(column,tbuf);
}

void amdl_rel(int ofs,char *format,...)
{
	va_list a;
	va_start(a,format);
	if (!on)
		return;
	vsprintf(tbuf,format,a);
	add_col(col+ofs,tbuf);
}

void amdl_flush()
{
	int op,oc;
	if (!on)
		return;
	do {
		op = 0;
		oc = 0;
		for (col=0;col<AMDL_COLS;col++)
		{
			if (cols[col].top)
			{
				while (oc < col)
				{
					fputc('\t',log);
					oc++;
				}
				fputs(cols[col].top->txt,log);
				flush_line(col);
				op = 1;
			}
		}
		if (op)
			fputc('\n',log);
	} while (op);
	col = 0;
}

#endif
