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

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

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

	// extensions
	int force, help, offline, repeat;
	char dir[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;
		version = 0;

		// extensions
		strcpy(dir, "");
		force = 0;
		help = 0;
		offline = 0;
		strcpy(prefix, "");
		repeat = 0;

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

		if (strstr(args[0], "files2cd") != NULL)
		{
			joliet = 1;
			multi = 1;
			rockRidge = 1;
			trackType = file;
		}

		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, ".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 (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, "--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 (strcmp(arg, "-mp3") == 0)
			trackType = mp3;
		else
		if (strcmp(arg, "--offline") == 0
			|| strcmp(arg, "-o") == 0)
			offline = 1;
		else
		if (strcmp(arg, "--repeat") == 0)
			repeat = 1;
		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, "--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" };
		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 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("\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("\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-J, -joliet\tsee mkisofs\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--repeat"
			"\tburn the last session again\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- Burn the last session again\n"
			"\t%s [options] --repeat\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();
	}
};
