/***********************************************
 *  listfile.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 *active_list, *edit_list;

extern DCharBuf *args;

extern char *PLAYMODES[], *SEARCHPRF[];

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

static char tmpstr_lf[LIST_COMM_SIZE], tmpstr2_lf[LIST_COMM_SIZE];

/************************************
 *       Playlist file manip        *
 ************************************/

void write_list_header(FILE * fd)
{
    time_t tim;
    char *time_ascii;

    tim = time(NULL);
    time_ascii = ctime(&tim);
    remove_newline(time_ascii);

    fprintf(fd, "# Playlist created by %s %s on %s\n\n",
	    NAME, VERSION, time_ascii);
}

void write_stream_line(FILE * fd, int ndx, DCharBuf * lst)
{
    char *tag, *file;
    int len;

    tag = get_stream(lst, ndx, STR_TAG);
    file = get_stream(lst, ndx, STR_FILE);

    if (tag) {
	len = (file - tag) - TAG_CODE_LEN + 1;
	if (len < (LIST_COMM_SIZE - TAG_CODE_LEN - 1)) {
	    strncpy(tmpstr_lf, tag, len);
	    tmpstr_lf[len - 1] = ZCHAR;
	} else
	    *tmpstr_lf = ZCHAR;
    } else
	*tmpstr_lf = ZCHAR;

    fprintf(fd, "%s %d %s\n", TAG_HEADER, lst->buf[ndx].info, tmpstr_lf);
    fprintf(fd, "%s\n", file);
}

void write_list_info(FILE * fd, ListDef * lst)
{
    char view[32];

    if (!fd || !lst)
	return;

    switch (lst->listview) {
    case TAG_FILE_PREF:
	strcpy(view, "viewTF");
	break;
    case TAG_PATH_PREF:
	strcpy(view, "viewTPF");
	break;
    case PATH_FILE_PREF:
	strcpy(view, "viewPF");
	break;
    case FILE_ONLY_PREF:
	strcpy(view, "viewF");
	break;
    default:
	strcpy(view, "unknown");
    }

    if (is_any_space(lst->dcb->name))
	fprintf(fd, "%s \"%s\" %s %s %d %d %d\n", LIST_INFO_TAG,
		lst->dcb->name, PLAYMODES[lst->playmode], view,
		lst->dcb->pos, lst->play_weight, lst->skip_weight);
    else
	fprintf(fd, "%s %s %s %s %d %d %d\n", LIST_INFO_TAG,
		lst->dcb->name, PLAYMODES[lst->playmode], view,
		lst->dcb->pos, lst->play_weight, lst->skip_weight);
}

void save_list(char *file, DCharBuf * lst)
{
    FILE *fd;
    int i, len;

    len = lst->len;

    if (!len)
	show_user(DEBUG_MSG " \"%s\" list is empty", lst->name);
    else if (!(fd = myfopen(file, "w+")))
	show_user(ERROR_MSG " Could not open \"%s\" : %s",
		  file, strerror(errno));
    else {
	write_list_header(fd);

	for (i = 0; i < len; i++)
	    write_stream_line(fd, i, lst);

	fclose(fd);
	show_user(STATUS_MSG" Saved %d entry(s) from \"%s\" list to \"%s\"",
		  len, lst->name, file);
    }
}

void /* user */ save_list_comm()
{
    char *file;

    file = g_dbuf(args, 1);

    if (!file)
	print_cmnd_help(SAVE_LIST);
    else if (!edit_list)
	show_user(DEBUG_MSG " Edit list undefined");
    else
	save_list(file, edit_list->dcb);
}

void /* user */ save_all_lists()
{
    ListDef *lst;
    DCharBuf *dcb;
    int i, len, entries, nlists;
    char *file;
    FILE *fd;

    file = g_dbuf(args, 1);
    entries = nlists = 0;

    if (!file)
	print_cmnd_help(SAVE_ALL_LISTS);
    else if (!g_list_base())
	show_user(DEBUG_MSG " No lists defined");
    else if (!(fd = myfopen(file, "w+")))
	show_user(ERROR_MSG " Failed file open of \"%s\" : %s",
		  file, strerror(errno));
    else {
	write_list_header(fd);
	lst = g_list_base();

	while (lst) {
	    write_list_info(fd, lst);
	    dcb = lst->dcb;
	    len = dcb->len;
	    nlists++;

	    for (i = 0; i < len; i++) {
		write_stream_line(fd, i, dcb);
		entries++;
	    }

	    lst = lst->next;
	}

	fclose(fd);
	show_user(STATUS_MSG " Saved %d entry(s) from %d list(s) to \"%s\"",
		  entries, nlists, file_from_path(file));
    }
}

int get_playmode(char *mode)
{
    if (strcmp(mode, PLAYMODES[ONCE_MODE]) == 0)
	return ONCE_MODE;
    else if (strcmp(mode, PLAYMODES[REPEAT_MODE]) == 0)
	return REPEAT_MODE;
    else if (strcmp(mode, PLAYMODES[TRANDOM_MODE]) == 0)
	return TRANDOM_MODE;
    else if (strcmp(mode, PLAYMODES[SRANDOM_MODE]) == 0)
	return SRANDOM_MODE;
    else if (strcmp(mode, PLAYMODES[LEARN_MODE]) == 0)
	return LEARN_MODE;
    else
	return ONCE_MODE;
}

int get_listview(char *mode)
{
    if (strcmp(mode, "viewTF") == 0)
	return TAG_FILE_PREF;
    else if (strcmp(mode, "viewTPF") == 0)
	return TAG_PATH_PREF;
    else if (strcmp(mode, "viewPF") == 0)
	return PATH_FILE_PREF;
    else if (strcmp(mode, "viewF") == 0)
	return FILE_ONLY_PREF;
    else
	return TAG_FILE_PREF;;
}

void /* user */ load_all_lists()
{
    ListDef *lst;
    FILE *fd;
    int entries, nlists, alists, pnfo, pos, plw, skw;
    char *cm, *cmem, *file, *info, *name, *mode, *view;

    file = g_dbuf(args, 1);
    entries = nlists = alists = 0;
    lst = NULL;

    if (!file)
	print_cmnd_help(LOAD_ALL_LISTS);
    else if (!(fd = myfopen(file, "r")))
	show_user(ERROR_MSG " Failed file open of \"%s\" : %s",
		  file, strerror(errno));
    else {
	while (!feof(fd)) {
	    get_fline(fd, tmpstr_lf, LIST_COMM_SIZE);

	    if (strcmp(tmpstr_lf, "") != 0) {
		info = grep_str(LIST_INFO_TAG, tmpstr_lf);

		if (info) {
		    cm = cmem = NULL;
		    cm = tokenize(info, &cmem, ' ');
		    if (cm) name = cm;
		    else name = NULL;
		    cm = tokenize(NULL, &cmem, ' ');
		    if (cm) mode = cm;
		    else mode = NULL;
		    cm = tokenize(NULL, &cmem, ' ');
		    if (cm) view = cm;
		    else view = NULL;
		    cm = tokenize(NULL, &cmem, ' ');
		    if (cm) pos = atoi(cm);
		    else pos = 0;
		    cm = tokenize(NULL, &cmem, ' ');
		    if (cm) plw = atoi(cm);
		    else plw = 0;
		    cm = tokenize(NULL, &cmem, ' ');
		    if (cm) skw = atoi(cm);
		    else skw = 0;

		    if (name) {
			lst = g_list(name);
			if (!lst) {
			    a_list(name);
			    lst = g_list(name);
			    if (!active_list)
				active_list = lst;
			    if (!edit_list)
				edit_list = lst;
			    alists++;
			}
			nlists++;
		    }

		    if (lst) {
			lst->playmode = get_playmode(mode);
			lst->listview = get_listview(view);
			lst->dcb->pos = pos;
			lst->play_weight = plw;
			lst->skip_weight = skw;
		    }

		    continue;
		}

		info = grep_str(TAG_HEADER, tmpstr_lf);

		if (info) {
		    pnfo = 0;
		    memset(tmpstr2_lf, ZCHAR, LIST_COMM_SIZE);
		    sscanf(tmpstr_lf,
			   TAG_HEADER " %d %1024c", &pnfo, tmpstr2_lf);
		    if (!feof(fd)) {
			get_fline(fd, tmpstr_lf, LIST_COMM_SIZE);
			if (*tmpstr2_lf != ZCHAR)
			    strcat(tmpstr2_lf, TAG_CODE);
			strcat(tmpstr2_lf, tmpstr_lf);
			if (lst) {
			    add_stream(tmpstr2_lf, lst->dcb, TRUE, FALSE);
			    sp_dbuf(lst->dcb, lst->dcb->len - 1, pnfo);
			    entries++;
			}
		    }
		} else if (lst && *tmpstr_lf != '#') {
		    add_stream(tmpstr_lf, lst->dcb, FALSE, FALSE);
		    entries++;
		}
	    }
	}

	if (!nlists)
	    show_user(DEBUG_MSG " No lists defined in \"%s\"", file);
	else {
	    verify_lists();
	    update_list_env();
	    if (alists)
		show_user(STATUS_MSG " Created %d new list(s)", alists);
	    show_user(STATUS_MSG " Added %d entry(s) to %d list(s)",
		      entries, nlists);
	}

	fclose(fd);
    }
}


void load_list(char *file, DCharBuf * lst)
{
    char *tag;
    int len, info;
    FILE *fd;

    fd = myfopen(file, "r");
    len = lst->len;
    info = 0;

    if (!fd)
	show_user(ERROR_MSG " Failed file open of \"%s\" : %s",
		  file, strerror(errno));
    else {
	while (!feof(fd)) {
	    get_fline(fd, tmpstr_lf, LIST_COMM_SIZE);

	    if (strcmp(tmpstr_lf, "") != 0) {
		tag = grep_str(TAG_HEADER, tmpstr_lf);
		if (tag) {
		    memset(tmpstr2_lf, ZCHAR, LIST_COMM_SIZE);
		    sscanf(tmpstr_lf,
			   TAG_HEADER " %d %1024c", &info, tmpstr2_lf);
		    if (!feof(fd)) {
			get_fline(fd, tmpstr_lf, LIST_COMM_SIZE);
			if (*tmpstr2_lf != ZCHAR)
			    strcat(tmpstr2_lf, TAG_CODE);
			strcat(tmpstr2_lf, tmpstr_lf);
			add_stream(tmpstr2_lf, lst, TRUE, FALSE);
			sp_dbuf(lst, lst->len - 1, info);
		    }
		} else if (*tmpstr_lf != '#')
		    add_stream(tmpstr_lf, lst, FALSE, FALSE);
	    }
	}

	fclose(fd);
	show_user(STATUS_MSG " Added %d entry(s) to \"%s\" list",
		  lst->len - len, lst->name);
    }
}

void /* user */ load_list_comm()
{
    char *file;

    file = g_dbuf(args, 1);

    if (!file)
	print_cmnd_help(LOAD_LIST);
    else if (!edit_list)
	show_user(DEBUG_MSG " Edit list undefined");
    else {
	load_list(file, edit_list->dcb);
	update_list_env();
    }
}
