/*
    This file is part of xmms-curses, copyright 2003-2005 Knut Auvor Grythe.

    xmms-curses 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.

    xmms-curses 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 xmms-curses; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include <audacious/audctrl.h>
#include <stdlib.h>
#include <ncursesw/curses.h>
#include <libgen.h>
#define __USE_GNU // to get strcasestr
#include <string.h>
#include "curses_printf.h"
#include "kbd_constants.h"
#include "main.h"
#include "playlist.h"
#include "dbus.h"

#include <time.h>

extern struct timespec interval;
extern playlist list;
extern windows wins;

static void jumpwin_repaint(void)
{
	mvwtitledhline(wins.title, 0, "Search results");
	wnoutrefresh(wins.title);
}

static gint match(gchar *title, gchar *string)
{
	if(strlen(string) == 0) return 1;
	gchar *token;
        gchar *cp;
	cp = g_strdup(string);
	token = (gchar*)g_strsplit(cp, " ",0);
	while(token){
		if(!strcasestr(title, token)) {
			g_free(cp);
			return 0;
		}
		token = strtok(NULL, " ");
	}
	g_free(cp);
	return 1;
}

static gint playlist_search(gchar *search, gint *results, gint prev_hits)
{
	gint i;
	gint hits = 0;

	if (prev_hits == -1) {
		for (i=0; i<(list.length); i++) {
			if (match(list.song[i].file, search)) {
				results[hits++] = i;
			}
		}
	} else {
		gint * old_results = (gint*)malloc(prev_hits * sizeof(gint));
		for (i=0; i<prev_hits; i++) {
			old_results[i] = results[i];
		}
		for (i=0; i<prev_hits; i++) {
			if (match(list.song[old_results[i]].file, search)) {
				results[hits++] = old_results[i];
			}
		}
		g_free(old_results);
	}
	return hits;
}

void playlist_jump(void)
{
	gint len = 0;
	gchar buffer[128];
	playlist plist;
	gint repaint = true;
	gint old_cursor = curs_set(1); // enable cursor

	plist.song_mask = (gint*)malloc(list.length * sizeof(gint));
	plist.pos = -1;
	plist.prev_pos = -1;
	plist.length = playlist_search("", plist.song_mask, -1);
	plist.selector = 0;
	plist.scrolledto = 0;
	plist.song = list.song;

	buffer[0] = '\0';

	while (true) {
		gint c;
		gint finished = false;
		gint search = false;
		gint pl_height, pl_width;

		if (wins.term_resized == true) {
			wins.term_resized = false; // Unset trigger
			resize_windows();
			repaint = true;
		}

		getmaxyx(wins.list, pl_height, pl_width);

		while((c = getch()) != ERR) {
			switch (c) {
				case KEY_UP:
					if ( plist.selector > 0 )
						--plist.selector;
					break;
				case KEY_DOWN:
					if ( plist.selector < plist.length-1 )
						++plist.selector;
					break;
				case KEY_PPAGE:
					if (plist.selector >= pl_height)
						plist.selector -= pl_height;
					else
						plist.selector = 0;
					break;
				case KEY_NPAGE:
					if (plist.selector < plist.length-pl_height)
						plist.selector += pl_height;
					else
						plist.selector = plist.length-1;
					break;
				case ESCAPE:
					g_free(plist.song_mask);
					finished = true;
					break;
				case ENTER:
					if (plist.length > 0) {
						audacious_remote_set_playlist_pos(dbus_proxy, plist.song_mask[plist.selector]);
						audacious_remote_play(dbus_proxy);
						g_free(plist.song_mask);
						finished = true;
					}
					break;
				case KEY_BACKSPACE:
					if (len == 0) break;
					buffer[--len] = '\0';
					search = true;
					//plist.selector = 0;
					plist.length = -1; //make playlist_search start from scratch
					break;
				default: //where we handle the characters
					if (len == 127) break; //we don't like overflows
					if (c < 32) break; //no control characters
					buffer[len] = c;
					buffer[++len] = '\0';
					search = true;
					//plist.selector = 0;
					break;
			}
		}

		if (finished) {
			if (old_cursor != ERR)
				curs_set(old_cursor); // restore cursor
			return;
		}

		if (search) {
			gint old_hits = plist.length;
			plist.length = playlist_search(buffer, plist.song_mask, plist.length);
			if (plist.length != old_hits) {
				plist.scrolledto = 0;
			}
		}

		playlist_paint(&plist);

		gint x, y;
		mvwaddnstrf(wins.status, 0, 0, "Searching for: %s", -1, buffer);
		getyx(wins.status, y, x);
		wclrtoeol(wins.status);
		mvwchgat(wins.status, 0, 0, -1, A_BOLD, 1, NULL);

		mvwaddnstrf(wins.status, 1, 0, "Results found: %i", -1, plist.length);
		wclrtoeol(wins.status);
		wchgat(wins.status, -1, A_NORMAL, 1, NULL);
		wmove(wins.status, y, x);

		wnoutrefresh(wins.status);

		if (repaint) {
			repaint = false;
			jumpwin_repaint();
		}

		doupdate();
		nanosleep(&interval, NULL);
	}
}
