/***********************************************
 *  queue.c                                 
 *                                            
 *  Copyright 2001 Eric Kratzer.              
 *  Includes Xaudio software Copyright (C)
 *           1996-2000 Xaudio Corporation
 *           All Rights Reserved.          
 *
 *  This file is part of imp3sh.
 *                                            
 *  imp3sh is free software; you can distribute
 *  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.
 *
 *  imp3sh 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 recieved a copy of the GNU
 *  General Public License along with imp3sh; if
 *  not, write to the Free Software Foundation,
 *  Inc., 59 Temple Place, Suite 330, Boston MA
 *  02111-1307 USA
 ************************************************/

/************************************
 *          Include Files           *
 ************************************/

#include "imp3sh.h"

#define LIST_COMM_SIZE (COMM_SIZE*2)

/************************************
 *       External References        *
 ************************************/

extern ListDef *history, *edit_list;

extern DCharBuf *args;

extern char *c_path;

extern flag_t inside_queue, read_file_tags, sort_mode;

/************************************
 *        Local variables           *
 ************************************/

static char tmpstr_q[LIST_COMM_SIZE];

/************************************
 *     Stream queue functions       *
 ************************************/

int in_queue()
{
    if (history->dcb->len && (history->dcb->pos < (history->dcb->len - 1)))
	return TRUE;
    else
	return FALSE;
}

void /* user */ clear_queue()
{
    c_dbuf(history->dcb);
    inside_queue = FALSE;
    show_user(STATUS_MSG " Queue cleared");
}

void add_queue(char *info)
{
    char *tagptr;
    flag_t tagpresent;

    if (!info)
	return;

    tagpresent = FALSE;
    tagptr = grep_str(TAG_CODE, info);
    if (tagptr) tagpresent = TRUE;

    add_stream(info, history->dcb, tagpresent, read_file_tags);
    history->dcb->pos = history->dcb->len - 1;
}

void /* user */ print_queue()
{
    char *pat;
    int i, len, pos, hlen;

    hlen = history->dcb->len;

    if (!hlen)
	add_outbuffer(DEBUG_MSG " Queue is empty");
    else {
	pat = g_dbuf(args, 1);
	len = get_strlen(pat);
	pos = history->dcb->pos;

	for (i = 0; i < hlen; i++) {
	    get_stream_id(history, i, tmpstr_q);

	    if (len && grep_against_args(1, tmpstr_q) == FALSE)
		continue;

	    if (i == pos)
		add_outbuffer(PNTR_MSG " %d> %s", i, tmpstr_q);
	    else
		add_outbuffer(LIST_MSG " %d> %s", i, tmpstr_q);
	}
    }

    flush_outbuffer();
}

void queue_directory(char *dir)
{
    DCharBuf *files, *dirlist, *dcb;
    int i, len;

    if (!dir)
	return;

    dirlist = i_dbuf("temp", 256, DCHAR_GROW);
    files = i_dbuf("files", 256, DCHAR_GROW);

    show_user(STATUS_MSG " Recursively queueing files in \"%s\" ...", dir);
    a_dbuf(dirlist, dir);

    while (dirlist->len)
	add_dir(TRUE, dirlist, files);

    chdir(c_path);

    if (files->len) {
	dcb = history->dcb;
	len = files->len;

	if (len > 1) {
	    sort_mode = TAG_FILE_PREF;
	    qsort((void *) files->buf, len, sizeof(DCBNode), compare_list);
	}

	for (i = 0; i < len; i++)
	    a_dbuf(dcb, g_dbuf(files, i));

	show_user(STATUS_MSG " Queued %d file(s) from \"%s\"", len, dir);
    } else
	show_user(DEBUG_MSG " No playable files found in \"%s\"", dir);

    f_dbuf(dirlist);
    f_dbuf(files);
}

void /* user */ queue_files_comm()
{
    struct stat sstat;
    char *file;
    int ndx;

    ndx = 1;
    file = g_dbuf(args, ndx++);

    if (!file) {
	print_cmnd_help(QUEUE_FILE);
	return;
    }

    while (file) {
	if (is_url(file))
	    add_stream(file, history->dcb, FALSE, FALSE);
	else {
	    if (*file != '/') {
		sprintf(tmpstr_q, "%s/%s", c_path, file);
		file = tmpstr_q;
	    }

	    if (stat(file, &sstat))
		show_user(ERROR_MSG " Error reading file \"%s\" : %s",
			  file, strerror(errno));
	    else if (sstat.st_mode & S_IFDIR)
		queue_directory(file);
	    else {
		if (check_format(file))
		    add_stream(file, history->dcb, FALSE, read_file_tags);
		else
		    show_user(ERROR_MSG
			      " No suitable player defined for: \"%s\"", file);
	    }
	}
	file = g_dbuf(args, ndx++);
    }

    update_list_env();
}

void queue_list_grep(ListDef * from)
{
    int i, add, len;

    add = 0;
    len = from->dcb->len;

    for (i = 0; i < len; i++) {
	get_stream_id(from, i, tmpstr_q);
	if (grep_against_args(1, tmpstr_q)) {
	    add++;
	    a_dbuf(history->dcb, g_dbuf(from->dcb, i));
	}
    }

    show_user(STATUS_MSG " %d entry(s) added to queue", add);
}

void queue_list_range(char *str, ListDef * from)
{
    int i, low, high;

    get_digit_range(str, &low, &high, 0, from->dcb->len - 1);

    if (low < high &&
	(low >= 0 && low < from->dcb->len) &&
	(high >= 0 && high < from->dcb->len)) {
	show_user(STATUS_MSG" Queuing \"%s\" list entry(s) in range %d-%d:",
		  from->dcb->name, low, high);

	for (i = low; i <= high; i++)
	    a_dbuf(history->dcb, g_dbuf(from->dcb, i));

	show_user(STATUS_MSG " %d entry(s) added to queue", (high - low) + 1);
    } else
	show_user(DEBUG_MSG " Bad index range");
}

void /* user */ queue_list_index()
{
    char *s, *smem, *str;
    int ndx;

    s = g_dbuf(args, 1);

    if (!s)
	print_cmnd_help(QUEUE_INDEX);
    else if (!edit_list)
	show_user(DEBUG_MSG " Edit list undefined");
    else {
	smem = NULL;
	str = tokenize(s, &smem, COMMA);

	while (str && *str != ZCHAR) {
	    if (is_digit_range(str))
		queue_list_range(str, edit_list);
	    else if (is_all_digits(str)) {
		ndx = atoi(str);

		if (ndx >= 0 && ndx < edit_list->dcb->len) {
		    a_dbuf(history->dcb, g_dbuf(edit_list->dcb, ndx));
		    show_user(STATUS_MSG
			      " \"%s\" list index %d added to queue",
			      edit_list->dcb->name, ndx);
		} else
		    show_user(DEBUG_MSG " index %d out of range", ndx);
	    } else
		queue_list_grep(edit_list);

	    str = tokenize(NULL, &smem, COMMA);
	}

	update_list_env();
    }
}
