#include "show.h"

/**
 * Copyright (C) 2001-2006 Tino Reichardt
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License Version 2, as
 * published by the Free Software Foundation.
 *
 * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
 */


/**
 * null terminated lines in one stralloc
 * - one for the left, one for the right side
 * - we use a special function to show some line
 */
stralloc space_left, space_right;


/**
 * lines_current - this is the current quantity of lines in both stralloc's
 * lines_start   - first line of the currently displayed info
 *
 ************************************
 * left      |     right
 * 3..17   18|20   21..maxx
 * .(17-3)   |     . (maxx-22)
 * .         |     .
 * maxy      |     maxy
 ************************************
 */
static int lines_current;   /* currently in our buffer */
static int lines_start;     /* current starting line */
static int lines_available; /* how many lines can be filled */


/**
 * internal functions
 */
static void show_main_init(void);
static void show_main_add_left(char *start, int len);
static void show_main_add_right(char *start, int len);
static void show_main_printline(stralloc *sa, int line);


/**
 * offset from the top
 */
#define Y_BEGIN  8
#define Y_BOTTOM (Y_BEGIN+3)


/**
 * this is a hardcoded maximum of lines we will provide
 */
#define MAXLINES 100

/**
 * show_main_init - initialize the strallocs
 *
 * @return nothing
 */
static void show_main_init(void)
{
	static int initdone=0;

	if (initdone == 0) {
		stralloc_init(&space_left);
		stralloc_init(&space_right);
		initdone=1;
	}

#if 0
	{
	stralloc sa;
	stralloc_init(&sa);
	stralloc_cats(&sa, "start:");
	stralloc_cat_u32pw(&sa, lines_start, 3, '0');
	stralloc_cats(&sa, " current:");
	stralloc_cat_u32pw(&sa, lines_current, 3, '0');
	stralloc_cats(&sa, " left.len:");
	stralloc_cat_u32pw(&sa, space_left.len, 4, '0');
	stralloc_cats(&sa, " right.len:");
	stralloc_cat_u32pw(&sa, space_right.len, 4, '0');
	stralloc_cats(&sa, " maxx:");
	stralloc_cat_u32pw(&sa, show_maxx, 3, '0');
	stralloc_cats(&sa, " maxy:");
	stralloc_cat_u32pw(&sa, show_maxy, 3, '0');
	stralloc_cats(&sa, " available:");
	stralloc_cat_u32pw(&sa, lines_available, 3, '0');
	show_gotoxy(2,3);
	show_sa(&sa);
	stralloc_free(&sa);
	flush();
	}
#endif

	return;
}


/**
 * show_main_add_left - add sth. to the space of the left stralloc
 *
 * @param start  pointer to some string
 * @param len    length to add of that string
 * @return       nothing
 */
static void show_main_add_left(char *start, int len)
{
	if (!stralloc_catb(&space_left, start, len)) die_nomem();
	if (!stralloc_0(&space_left)) die_nomem();

	return;
}


/**
 * show_main_add_right - add sth. to the space of the right stralloc
 *
 * @param start  pointer to some string
 * @param len    length to add of that string
 * @return       nothing
  */
static void show_main_add_right(char *start, int len)
{
#if 0
	if (!stralloc_cat_u32pw(&space_right, lines_current, 2, '0')) die_nomem();
	if (!stralloc_cats(&space_right, " - : ")) die_nomem();
#endif
	if (!stralloc_catb(&space_right, start, len)) die_nomem();
	if (!stralloc_0(&space_right)) die_nomem();

	return;
}


/**
 * show_main_printline - print some line from a "window stralloc"
 *
 * @return       nothing
 */
static void show_main_printline(stralloc *sa, int line)
{
	char *s;
	int i, l;

	for (l=i=0, s=sa->s; i < (int)sa->len; i+=str_len(s+i)+1) {
		if (l == line) {
			show(s+i);
#if 0
			buffer_puts(buffer_2, "(");
			buffer_puts(buffer_2, s+i);
			buffer_puts(buffer_2, ")\n\n");
			buffer_flush(buffer_2);
#endif
		}
		l++; /* next line */
	}

	return;
}


/**
 * show_main_scroll - clear out the main window
 *
 * @param x  scroll down / up for the length of x
 * @return   nothing
 */
void show_main_scroll(int x)
{
	int i=0;

	/* x == 0 -> do nothing! */
	if (x == 0) return;

	show_main_init();

	/* scroll up by x */
	if (x > 0) {

		/* calculate, if scrolling up is needed! */
		if (lines_available >= lines_current-lines_start-1)
			return;

		/* set lines_start to some new value */
		if (lines_start + x <= lines_current) {
			lines_start += x;
		} else {
			lines_start=lines_current;
		}
	}

	/* scroll down by x */
	if (x < 0) {
		x*=-1;

		/* calculate, if scrolling down is needed! */
		if (lines_start == 0)
			return;

		/* set lines_start to some new value */
		if (lines_start - x >= 0) {
			lines_start -= x;
		} else {
			lines_start=0;
		}
	}

	/* clear all old lines */
	show_main_clear();

	/* redraw all lines */
	for (i=0; i <= lines_available; i++) {
		if (i) {
			show_gotoxy(3, i+Y_BEGIN);
			show_main_printline(&space_left, lines_start+i);
		}
		show_gotoxy(21, i+Y_BEGIN);
		show_main_printline(&space_right, lines_start+i);
	}

	return;
}


/**
 * show_main_reset - clear out the main window and reset buffer
 * - should be done after windows resizing and the like...
 *
 * @return nothing
 */
void show_main_reset(void)
{
	show_main_init();

	/* clear old lines */
	show_main_clear();

	/* reset our counter and the line buffer */
	lines_start=0;
	lines_current=0;
	lines_available=show_maxy-Y_BOTTOM;
	if (!stralloc_copys(&space_left, "")) die_nomem();
	if (!stralloc_copys(&space_right, "")) die_nomem();

	return;
}

/**
 * show_main_clear - clear out the main window
 *
 * @return nothing
 */
void show_main_clear(void)
{
	int i, lines;

	show_main_init();

	/* calculate what we have to clear */
	if (lines_current >= lines_available) {
		lines = lines_available;
	} else {
		lines = lines_current-1;
	}

	/* clear filled lines */
	while (lines >= 0) {
		/* left side */
		if (lines != 0) {
			/* not overwrite my: "T   Trackliste:" */
			show_gotoxy(3, lines+Y_BEGIN);
			for (i=0; i<15; i++) show("#");
		}
		/* right side */
		show_gotoxy(21, lines+Y_BEGIN);
		for (i=0; i<show_maxx-22; i++) show("#");
		lines--;
	}
	flush();

	return;
}

/**
 * draw sth. into the main window, which is divided into left|right
 * - when the bottom is reached, the top-lines are truncated
 *
 * @param type    1 = scrolling / 0 = permanent
 * @param c_left  length, which is used for colors in the left window
 * @param left    string, for the left window
 * @param c_right length, which is used for colors in the right window
 * @param right   string, for the right window
 * @return        nothing
 */
void show_main_color_doit(int scrolling, int c_left, stralloc *left, int c_right, stralloc *right)
{
	show_main_init();

	/* ignore this */
	if (lines_current+1 >= MAXLINES) {
		die_msg(111, ">=MAXLINES");
		return;
	}

	/* add the new stuff to our buffers */
	if (left->len-c_left > 15) {
		show_main_add_left(left->s, 15+c_left);
	} else {
		show_main_add_left(left->s, left->len);
	}

	if (right->len-c_right > (unsigned int)show_maxx-22) {
		show_main_add_right(right->s, show_maxx-22+c_right);
	} else {
		show_main_add_right(right->s, right->len);
	}

	/* add the new line to the counter */
	lines_current++;
	if (lines_current-1 > lines_available) {
		if (scrolling) show_main_scroll(+1);
		return;
	}

	/* left window */
	show_gotoxy(3, Y_BEGIN+lines_current-1);
	show_main_printline(&space_left, lines_current-1);

	/* right window */
	show_gotoxy(21, Y_BEGIN+lines_current-1);
	show_main_printline(&space_right, lines_current-1);

	return;
}

