/*
 * @(#)CommandArgs.h
 *
 * This file is part of webCDwriter - Network CD Writing.
 *
 * Copyright (C) 2000-2004 Jörg P. M. Haeger
 *
 * webCDwriter is free software. See rcdrecord.cpp for details.
 */

#include <stdio.h>
#include "config.h"
#include "Error.h"
#include "Version.h"

class CommandArgs {
	char **args;
	enum TrackType { audio, data, file, mp3, ogg } trackType;
	int *files;
	enum TrackType *types;
public:
	int numOfFiles;

	// cdrecord
	char blank[1024];
	int dummy;
	char host[1024];
	int multi, port, speed, verbose, verify, version;

	// extensions
	int copies;
	int force, help, list, offline;
	char dir[1024], id[1024], medium[1024], prefix[1024];

	// mkisofs
	int hfs, joliet, rockRidge;

	CommandArgs(int argc, char *args[]) {
		this->args = args;
		trackType = data;
		files = new int[argc];
		types = new enum TrackType[argc];
		numOfFiles = 0;

		// cdrecord
		strcpy(blank, "");
		dummy = 0;
		strcpy(host, defaultHost);
		multi = 0;
		port = defaultPort;
		speed = -1;
		verbose = 0;
		verify = 0;
		version = 0;

		// extensions
		copies = 1;
		strcpy(dir, "");
		force = 0;
		help = 0;
		strcpy(id, "");
		list = 0;
		strcpy(medium, "CD-R");
		offline = 0;
		strcpy(prefix, "");

		// mkisofs
		hfs = 0;
		joliet = 0;
		rockRidge = 0;

		if (strstr(args[0], "files2") != NULL) {
			joliet = 1;
			multi = 1;
			rockRidge = 1;
			trackType = file;
			if (strstr(args[0], "DVD") != NULL)
				strcpy(medium, "DVD+RW");
		}

		readConfigFile();

		for (int i = 1; i < argc; i++) {
			char *arg = args[i];
//			printf("%s\n", arg);

			if (cdrecord(args[i]))
				;
			else
			if (mkisofs(args[i]))
				;
			else
			if (extension(args[i]))
				;
			else
			if (arg[0] != '-' || arg[1] == 0
					|| strcmp(arg, "--stdin") == 0) {
				files[numOfFiles] = i;
				types[numOfFiles] = trackType;

				if (trackType != file && strlen(arg) > 3) {
					char *suffix = &arg[strlen(arg) - 4];
					if (strcasecmp(suffix, ".mp3") == 0)
						types[numOfFiles] = mp3;
					else
					if (strcasecmp(suffix, ".ogg") == 0)
						types[numOfFiles] = ogg;
					else
					if (strcasecmp(suffix, ".wav") == 0)
						types[numOfFiles] = audio;
				}

				numOfFiles++;
			}
			else {
				showUsage();
				throw new Error(
					"unknown argument: \"%s\"\n", arg);
			}
		}

		if (argc == 1 || help) {
			showUsage();
			exit(0);
		}

		if (version) {
			printf("%s - %s\n", product, subTitle);
			printf("Version: %s\n", ::version);
			printf("Author: %s, %s\n\n", author, eMail);
			printf("This is a client of %s\n(see %s).\n\n",
				project, projectHome);
			printf("%s uses cdrecord from Jörg Schilling "
				"for the real work. Thanks!\n\n",
				project);
			exit(0);
		}
	}

	int cdrecord(const char *arg) {
		if (strcmp(arg, "-audio") == 0)
			trackType = audio;
		else
		if (strcmp(arg, "-data") == 0)
			trackType = data;
		else
		if (strcmp(arg, "-dummy") == 0)
			dummy = 1;
		else
		if (sscanf(arg, "medium=%s", medium) == 1) {
		}
		else
		if (strcmp(arg, "-multi") == 0)
			multi = 1;
		else
		if (strcmp(arg, "-v") == 0)
			verbose = 1;
		else
		if (strcmp(arg, "-version") == 0)
			version = 1;
		else
		if (sscanf(arg, "blank=%s", blank) == 1) {
			if (strcmp(blank, "all") != 0
					&& strcmp(blank, "fast") != 0) {
				showUsage();
				throw new Error(
					"unsupported blank type: \"%s\"\n",
					blank);
			}
		}
		else
		if (sscanf(arg, "dev=%[^:]:%d", host, &port) >= 1)
			;
		else
		if (sscanf(arg, "speed=%d", &speed) == 1)
			;
		else
			return 0;
		return 1;
	}

	int extension(const char *arg) {
		if (sscanf(arg, "copies=%d", &copies) == 1)
			;
		else
		if (sscanf(arg, "--dir=%s", dir) == 1)
			;
		else
		if (strcmp(arg, "-file") == 0
				|| strcmp(arg, "-files") == 0) {
			multi = 1;
			trackType = file;
		}
		else
		if (strcmp(arg, "--force") == 0
				|| strcmp(arg, "-f") == 0)
			force = 1;
		else
		if (strcmp(arg, "--help") == 0)
			help = 1;
		else
		if (sscanf(arg, "--id=%[^;]", id) == 1)
			;
		else
		if (strcmp(arg, "--list") == 0)
			list = 1;
		else
		if (strcmp(arg, "-mp3") == 0)
			trackType = mp3;
		else
		if (strcmp(arg, "--offline") == 0
				|| strcmp(arg, "-o") == 0)
			offline = 1;
		else
		if (strcmp(arg, "-ogg") == 0)
			trackType = ogg;
		else
		if (strcmp(arg, "--simulate") == 0
				|| strcmp(arg, "-s") == 0)
			dummy = 1;
		else
		if (strcmp(arg, "--test") == 0)
			dummy = 1;
		else
		if (strcmp(arg, "--verbose") == 0)
			verbose = 1;
		else
		if (strcmp(arg, "--verify") == 0)
			verify = 1;
		else
		if (strcmp(arg, "--version") == 0)
			version = 1;
		else
		if (sscanf(arg, "--prefix=%s", prefix) == 1)
			;
		else
			return 0;
		return 1;
	}

	const char *getTrack(int n) {
		return args[files[n]];
	}

	const char *getType(int n) {
		char *typeStrs[] = { "wav", "iso", "file", "mp3", "ogg" };
		return typeStrs[types[n]];
	}

	int mkisofs(const char *arg) {
		if (strcmp(arg, "-h") == 0
				|| strcmp(arg, "-hfs") == 0)
			hfs = 1;
		else
		if (strcmp(arg, "-J") == 0
				|| strcmp(arg, "-joliet") == 0)
			joliet = 1;
		else
		if (strcmp(arg, "-r") == 0
				|| strcmp(arg, "-rational-rock") == 0)
			rockRidge = 1;
		else
			return 0;
		return 1;
	}

	void readConfigFile() {
		FILE *inStream = fopen(configFileName, "r");
		if (inStream != NULL) {
			char lineStr[1024];
			while (fgets(lineStr,
					sizeof lineStr, inStream) != NULL) {
				char str1[1024], str2[1024];
				if (sscanf(lineStr, "%[^=] = %s",
					str1, str2) < 2)
					continue;
				else
				if (strcasecmp(str1, "server") == 0)
					strcpy(host, str2);
				else
				if (strcasecmp(str1, "port") == 0)
					sscanf(str2, "%d", &port);
			}
			fclose(inStream);
		}
	}

	void showCdrecordUsage() {
		printf("%s: Usage: %s [options] track1...trackn\n",
			args[0], args[0]);
		printf("Options:\n");
		printf("\tblank=type\tblank a CD-RW disc"
			" (type=fast or type=all)\n");
		printf("\tdev=host[:port]\t\thost (and port) of CDWserver\n");
		printf("\t\t\t(the default is %s:%d)\n",
			defaultHost, defaultPort);
		printf("\tspeed=#\t\tset the prefered writing speed\n");
		printf("\t-audio\t\tsubsequent tracks are CD-DA audio tracks\n");
		printf("\t-data\t\tsubsequent tracks are CD-ROM data mode 1 (default)\n");
		printf("\t-dummy\t\trun cdrecord in simulation mode\n");
		printf("\tmedium=CD-R\tone of CD-R, DVD+RW, DVD+R, DVD-RW, DVD-R\n");
		printf("\t-multi\t\tdo not close the CD\n");
		printf("\t-v\t\tbe verbose\n");
		printf("\t-version\tshow the version of %s\n", product);
		printf("\n");
		printf("Extensions:\n");
		printf("\tcopies=#\tset the number of copies to burn\n");
		printf("\t-file"
			"\t\tadd subsequent files to a data CD using multisession\n"
			"\t\t\t(see \"files2cd --help\" for a shortcut)\n");
		printf("\t-f, --force\tignore unreadable files and directories\n");
		printf("\t-h, -hfs\tsee mkisofs\n");
		printf("\t--id=ID\t\tset an ID for the session\n");
		printf("\t-J, -joliet\tsee mkisofs\n");
		printf("\t--list"
			"\t\tlist the sessions that are on the server\n");
		printf("\t-mp3"
			"\t\tdecode subsequent MP3 tracks for an audio CD\n");
		printf("\t-o, --offline"
			"\texit after the reservation of the CD-writer\n");
		printf("\t-r, -rational-rock\tsee mkisofs\n");
		printf("\t--verify"
			"\tverify the CD after writing it\n");
		printf("\n");
		printf("Examples:\n");
		printf("Writing the image file cdimage.iso\n"
			"\t%s cdimage.iso\n\n", args[0]);
		printf("Creating an image and writing it\n"
			"\tmkisofs -r /bin | %s -\n\n", args[0]);
		printf("Copying the first track of a data CD\n"
			"\t%s /dev/[hd?|scd?]\n\n", args[0]);
		printf("Writing WAVs and MP3s to an audio CD\n"
			"\t%s 1.wav 2.mp3 ...\n\n",
			args[0]);
		printf("Adding the directory /bin to a data CD"
			"\n(CDWserver will "
			"create the image for you using multisession)\n"
			"\t%s -r -J -file /bin\n", args[0]);
		printf("\n");
	}

	void showFiles2cdUsage() {
		printf("Usage Information\n\n");
		printf("- Adding files to a data CD\n"
			"\t%s [options] file/directory ...\n", args[0]);
		printf("\n- show the sessions that are still available "
			"on the server\n"
			"\t%s --list\n", args[0]);
		printf("\n- burn the session given by the ID \"example\"\n"
			"\t%s [options] --id=example\n", args[0]);
		printf("\nOptions:\n");
		printf("\t--dir=DIR"
			"\tchange to directory DIR\n");
		printf("\t-o, --offline"
			"\texit after the reservation of the CD-writer\n");
		printf("\t--prefix=DIR"
			"\tset the base directory on the CD\n");
		printf("\t-s, --simulate"
			"\trun a test with laser off\n");
		printf("\t-v, --verbose"
			"\tshow all available runtime information\n");
		printf("\t--version"
			"\tshow the version information\n");
		printf("\n%s is a shortcut of "
			"\"rcdrecord -file -J -r -multi\".\n", args[0]);
		printf("See \"rcdrecord --help\" for more options.\n");
		printf("\n");
	}

	void showUsage() {
		if (strstr(args[0], "files2cd") != NULL)
			showFiles2cdUsage();
		else
			showCdrecordUsage();
	}
};
