#include "mcdp.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.
 */

/**
 * EXTD=ext data for disc
 * EXTT0=ext data for track 1
 * DYEAR=2004
 * DISCID=12345678 -> ignored!
 * DTITLE=artist / album
 * DGENRE=New Age
 * TTITLE0=artist / title 1
 * TTITLExx=artist / title xx
 * PLAYORDER=1,2,3,4 -> should we use it?
 */

static char *cddb_extd="EXTD";
static char *cddb_extt="EXTT";
static char *cddb_dyear="DYEAR";
static char *cddb_dgenre="DGENRE";
static char *cddb_dtitle="DTITLE";
static char *cddb_ttitle="TTITLE";
static char *cddb_porder="PLAYORDER";
static char *cddb_revision="# Revision: ";

/**
 * db_cddb - read a cddb file
 *
 * @return   zero on success, -1 on failure
 *           >0 if some data is missing
 */
int db_cddb(void)
{
	stralloc sa;
	buffer b;
	unsigned int l, n, r;
	//int todo;

	if (buffer_mmapread(&b, cd->cddbfile.s) == -1) {
		return -1;
	}

	stralloc_init(&sa);
	db_free();
	while (buffer_getnewline_sa(&b, &sa) == 1) {

		/* skip empty lines */
		if (sa.len == 1) continue;

		/* skip comments */
		if (sa.s[0] == '#') continue;
		sa.s[sa.len] = 0; /* ensure termination */

		/* remove \r\n and \n */
		if (sa.s[sa.len-2] == '\r') sa.s[sa.len-2]=0;
		if (sa.s[sa.len-1] == '\n') sa.s[sa.len-1]=0;

		/* extended data of disc */
		if (str_start(sa.s, cddb_extd)) {
			if (!stralloc_cats(&cd->t[0].extd, sa.s+5)) die_nomem();
			cd->t[0].extd.s[cd->t[0].extd.len]=0;
		}

		/* extended data of track xy */
		if (str_start(sa.s, cddb_extt)) {
			n = scan_uint(sa.s+4, &l);
			if (n > 0) {
				if (!stralloc_cats(&cd->t[l+1].extd, sa.s+5+n)) die_nomem();
				cd->t[l+1].extd.s[cd->t[l+1].extd.len]=0;
			}
		}

		/* disc year */
		if (str_start(sa.s, cddb_dyear)) {
			if (!stralloc_cats(&cd->year, sa.s+6)) die_nomem();
			cd->year.s[cd->year.len]=0;
		}

		/* title of disc */
		if (str_start(sa.s, cddb_dtitle)) {
			if (!stralloc_cats(&cd->t[0].name, sa.s+7)) die_nomem();
			cd->t[0].name.s[cd->t[0].name.len]=0;
		}

		/* track title */
		if (str_start(sa.s, cddb_ttitle)) {
			r=scan_uint(sa.s+6, &l);
			if (!stralloc_cats(&cd->t[l+1].name, sa.s+7+r)) die_nomem();
			cd->t[l+1].name.s[cd->t[l+1].name.len]=0;
		}

		/* genre of disc */
		if (str_start(sa.s, cddb_dgenre)) {
			if (!stralloc_cats(&cd->genre, sa.s+7)) die_nomem();
			cd->genre.s[cd->genre.len]=0;
		}

		/* revision of this file */
		if (str_start(sa.s, cddb_revision)) {
			scan_uint(sa.s+4, &l);
			cd->revision=l;
		}

		/* XXX, todo: playorder, comma seperated!
		 * - this is a design question
		 *   1. should we have just this one playorder?
		 *   2. should we use .workmandb with it's playlists?
		 *   3. should we create some new fileformat?
		 */
		if (str_start(sa.s, cddb_porder)) {
			if (!stralloc_cats(&cd->playorder, sa.s+10)) die_nomem();
			cd->playorder.s[cd->playorder.len]=0;
		}
	}
	buffer_close(&b);
	stralloc_free(&sa);

	return cd->db=DB_CDDB;
}

void db_cddb_write(void)
{
	stralloc sa;
	int fd, i;

	fd=open_trunc(cd->cddbfile.s);
	if (fd == -1) return;

	stralloc_init(&sa);

	if (!stralloc_cats(&sa, "# xmcd CD database file generated by mcdp "))
		die_nomem();
	if (!stralloc_cats(&sa, mcdp_version)) die_nomem();
	if (!stralloc_cats(&sa, "\n#\n# Track frame offsets:")) die_nomem();
	for (i=1; i <= cd->titles; i++) {
		if (!stralloc_cats(&sa, "\n#       ")) die_nomem();
		if (!stralloc_cat_uint(&sa, cd->t[i].cddb)) die_nomem();
	}
	if (!stralloc_cats(&sa, "\n#")) die_nomem();
	if (!stralloc_cats(&sa, "\n# Disc length: ")) die_nomem();
	if (!stralloc_cat_uint(&sa, cd->t[0].cddb/75)) die_nomem();
	if (!stralloc_cats(&sa, " seconds\n#\n# Revision: ")) die_nomem();
	if (!stralloc_cat_uint(&sa, cd->revision)) die_nomem();
	if (!stralloc_cats(&sa, "\n# Submitted via: mcdp ")) die_nomem();
	if (!stralloc_cats(&sa, mcdp_version)) die_nomem();
	if (!stralloc_cats(&sa, "\n#")) die_nomem();

	/* 1. DISCID */
	if (!stralloc_cats(&sa, "\nDISCID=")) die_nomem();
	if (!stralloc_cat_x32pw(&sa, cd->discid, 8, '0')) die_nomem();

	/* 2. DTITLE */
	if (!stralloc_cats(&sa, "\n")) die_nomem();
	if (!stralloc_cats(&sa, cddb_dtitle)) die_nomem();
	if (!stralloc_cats(&sa, "=")) die_nomem();
	if (cd->t[0].name.len) {
		if (!stralloc_cats(&sa, cd->t[0].name.s)) die_nomem();
	}

	/* 3. DYEAR */
	if (!stralloc_cats(&sa, "\n")) die_nomem();
	if (!stralloc_cats(&sa, cddb_dyear)) die_nomem();
	if (!stralloc_cats(&sa, "=")) die_nomem();
	if (cd->year.len)
		if (!stralloc_cats(&sa, cd->year.s)) die_nomem();

	/* 4. DGENRE */
	if (!stralloc_cats(&sa, "\n")) die_nomem();
	if (!stralloc_cats(&sa, cddb_dgenre)) die_nomem();
	if (!stralloc_cats(&sa, "=")) die_nomem();
	if (cd->genre.len)
		if (!stralloc_cats(&sa, cd->genre.s)) die_nomem();

	/* 5. TTITLExx */
	for (i=1; i <= cd->titles; i++) {
		if (!stralloc_cats(&sa, "\n")) die_nomem();
		if (!stralloc_cats(&sa, cddb_ttitle)) die_nomem();
		if (!stralloc_cat_uint(&sa, i-1)) die_nomem();
		if (!stralloc_cats(&sa, "=")) die_nomem();
		if (cd->t[i].name.len)
			if (!stralloc_cats(&sa, cd->t[i].name.s)) die_nomem();
	}

	/* 6. EXTD */
	if (!stralloc_cats(&sa, "\n")) die_nomem();
	if (!stralloc_cats(&sa, cddb_extd)) die_nomem();
	if (!stralloc_cats(&sa, "=")) die_nomem();
	if (cd->t[0].extd.len)
		if (!stralloc_cats(&sa, cd->t[0].extd.s)) die_nomem();

	/* 7. EXTTxx */
	for (i=1; i <= cd->titles; i++) {
		if (!stralloc_cats(&sa, "\n")) die_nomem();
		if (!stralloc_cats(&sa, cddb_extt)) die_nomem();
		if (!stralloc_cat_uint(&sa, i-1)) die_nomem();
		if (!stralloc_cats(&sa, "=")) die_nomem();
		if (cd->t[i].extd.len)
			if (!stralloc_cats(&sa, cd->t[i].extd.s)) die_nomem();
	}

	/* 8. PLAYORDER */
	if (!stralloc_cats(&sa, "\n")) die_nomem();
	if (!stralloc_cats(&sa, cddb_porder)) die_nomem();
	if (!stralloc_cats(&sa, "=")) die_nomem();
	if (cd->playorder.len)
		if (!stralloc_cats(&sa, cd->playorder.s)) die_nomem();
	if (!stralloc_cats(&sa, "\n")) die_nomem();

	/* write the full file */
	(void)write(fd, sa.s, sa.len);
	(void)close(fd);
	cd->db=DB_CDDB;

	return;
}

