/*
 * Schism Tracker - a cross-platform Impulse Tracker clone
 * copyright (c) 2003-2005 Storlek <storlek@rigelseven.com>
 * copyright (c) 2005-2008 Mrs. Brisby <mrs.brisby@nimh.org>
 * copyright (c) 2009 Storlek & Mrs. Brisby
 * copyright (c) 2010-2012 Storlek
 * URL: http://schismtracker.org/
 *
 * 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
 */

#include "headers.h"

#include <stdarg.h>

#include "it.h"
#include "song.h"
#include "page.h"
#include "vgamem.h"
#include "timer.h"
#include "mem.h"
#include "str.h"

#include "player/sndfile.h"

/* --------------------------------------------------------------------- */

static int status_bios = 0;
static char *status_text = NULL;
static timer_ticks_t text_timeout;

/* --------------------------------------------------------------------- */

static void status_text_flash_generic(const char *format, int bios, va_list ap)
{
	text_timeout = timer_ticks() + 1000;

	if (status_text)
		free(status_text);

	status_bios = bios;

	if (vasprintf(&status_text, format, ap) == -1) abort();

	status.flags |= NEED_UPDATE;
}

void status_text_flash(const char *format, ...)
{
	va_list ap;

	va_start(ap, format);

	status_text_flash_generic(format, 0, ap);

	va_end(ap);
}

void status_text_flash_bios(const char *format, ...)
{
	va_list ap;

	va_start(ap, format);

	status_text_flash_generic(format, 1, ap);

	va_end(ap);
}

void status_text_clear(void)
{
	/* oke */
	if (status_text) {
		free(status_text);
		status_text = NULL;
	}
}

/* --------------------------------------------------------------------- */

static inline int _loop_count(char *buf, int pos)
{
	if (current_song->repeat_count < 1 || (status.flags & CLASSIC_MODE)) {
		pos += draw_text("Playing", pos, 9, 0, 2);
	} else {
		pos += draw_text("Loop: ", pos, 9, 0, 2);
		pos += draw_text(str_from_num(0, current_song->repeat_count, buf), pos, 9, 3, 2);
	}
	return pos;
}

static inline void draw_song_playing_status(void)
{
	int pos = 2;
	char buf[16];
	int pattern = song_get_playing_pattern();

	pos = _loop_count(buf, pos);
	pos += draw_text(", Order: ", pos, 9, 0, 2);
	pos += draw_text(str_from_num(0, song_get_current_order(), buf), pos, 9, 3, 2);
	draw_char('/', pos, 9, 0, 2);
	pos++;
	pos += draw_text(str_from_num(0, csf_last_order(current_song), buf), pos, 9, 3, 2);
	pos += draw_text(", Pattern: ", pos, 9, 0, 2);
	pos += draw_text(str_from_num(0, pattern, buf), pos, 9, 3, 2);
	pos += draw_text(", Row: ", pos, 9, 0, 2);
	pos += draw_text(str_from_num(0, song_get_current_row(), buf), pos, 9, 3, 2);
	draw_char('/', pos, 9, 0, 2);
	pos++;
	pos += draw_text(str_from_num(0, song_get_pattern(pattern, NULL), buf), pos, 9, 3, 2);
	draw_char(',', pos, 9, 0, 2);
	pos++;
	draw_char(0, pos, 9, 0, 2);
	pos++;
	pos += draw_text(str_from_num(0, song_get_playing_channels(), buf), pos, 9, 3, 2);

	if (draw_text_len(" Channels", 62 - pos, pos, 9, 0, 2) < 9)
		draw_char(16, 61, 9, 1, 2);
}

static inline void draw_pattern_playing_status(void)
{
	int pos = 2;
	char buf[16];
	int pattern = song_get_playing_pattern();

	pos = _loop_count(buf, pos);
	pos += draw_text(", Pattern: ", pos, 9, 0, 2);
	pos += draw_text(str_from_num(0, pattern, buf), pos, 9, 3, 2);
	pos += draw_text(", Row: ", pos, 9, 0, 2);
	pos += draw_text(str_from_num(0, song_get_current_row(), buf), pos, 9, 3, 2);
	draw_char('/', pos, 9, 0, 2);
	pos++;
	pos += draw_text(str_from_num(0, song_get_pattern(pattern, NULL), buf), pos, 9, 3, 2);
	draw_char(',', pos, 9, 0, 2);
	pos++;
	draw_char(0, pos, 9, 0, 2);
	pos++;
	pos += draw_text(str_from_num(0, song_get_playing_channels(), buf), pos, 9, 3, 2);

	if (draw_text_len(" Channels", 62 - pos, pos, 9, 0, 2) < 9)
		draw_char(16, 61, 9, 1, 2);
}

static inline void draw_playing_channels(void)
{
	int pos = 2;
	char buf[16];

	pos += draw_text("Playing, ", 2, 9, 0, 2);
	pos += draw_text(str_from_num(0, song_get_playing_channels(), buf), pos, 9, 3, 2);
	draw_text(" Channels", pos, 9, 0, 2);
}

void status_text_redraw(void)
{
	timer_ticks_t now = timer_ticks();

	/* if there's a message set, and it's expired, clear it */
	if (status_text && now > text_timeout) {
		free(status_text);
		status_text = NULL;
	}

	if (status_text) {
		if (status_bios) {
			draw_text_bios_len(status_text, 60, 2, 9, 0, 2);
		} else {
			draw_text_len(status_text, 60, 2, 9, 0, 2);
		}
	} else {
		switch (song_get_mode()) {
		case MODE_PLAYING:
			draw_song_playing_status();
			break;
		case MODE_PATTERN_LOOP:
			draw_pattern_playing_status();
			break;
		case MODE_SINGLE_STEP:
			if (song_get_playing_channels() > 1) {
				draw_playing_channels();
				break;
			}
		default:
			break;
		}
	}
}
