/*
 * @(#)rcdrecord.cpp
 *
 * This file is part of webCDwriter - Network CD Writing.
 *
 * Copyright (C) 2000-2004 Jörg P. M. Haeger
 *
 * webCDwriter is free software; you can redistribute 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.
 *
 * webCDwriter 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 webCDwriter; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Jörg Haeger, 06.11.2000
 * eMail: info@JoergHaeger.de
 * http://JoergHaeger.de/webCDwriter/
 */

#include <locale.h>
#include <pwd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <termios.h>
#include <unistd.h>
#include "CommandArgs.h"
#include "Client2.h"

void readLoginFile(const char *loginFile,
	char *userID, char *userPassword) {
	FILE *inStream = fopen(loginFile, "r");
	if (inStream == NULL)
		return;

	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, "userID") == 0)
			strcpy(userID, str2);
		else
		if (strcasecmp(str1, "userPassword") == 0)
			strcpy(userPassword, str2);
	}
	fclose(inStream);
}

void writeLoginFile(const char *loginFile,
	const char *userID, const char *userPassword) {
	umask(S_IRWXG | S_IRWXO);
	FILE *outStream = fopen(loginFile, "w");
	if (outStream == NULL)
		throw new Error("Cannot write %s.", loginFile);

	fprintf(outStream, "userID=%s\n", userID);
	fprintf(outStream, "userPassword=%s\n", userPassword);
	fclose(outStream);
}

const char *readPassword(const char *message, char *passwd, int size) {
	struct termios settings;
	tcgetattr(0, &settings);
	settings.c_lflag &= ~ECHO;
	tcsetattr(0, TCSANOW, &settings);

	printf("%s", message);
	fgets(passwd, size, stdin);
	passwd[strlen(passwd) - 1] = 0;
	printf("\n");

	settings.c_lflag |= ECHO;
	tcsetattr(0, TCSANOW, &settings);
	return passwd;
}

const char *readString(const char *message, char *str, int size) {
	printf("%s", message);
	fgets(str, size, stdin);
	str[strlen(str) - 1] = 0;
	return str;
}

void login(Client client) {
	char userID[1024], userPassword[1024];
	userID[0] = 0;
	userPassword[0] = 0;

	const char *HOME = getenv("HOME");
	if (HOME == NULL)
		throw "Cannot get HOME.";
	char loginFile[1024];
	sprintf(loginFile, "%s/%s", HOME, userFileName);

	struct stat statBuf;
	if (stat(loginFile, &statBuf) == 0) {
		readLoginFile(loginFile, userID, userPassword);
		if (userID[0] != 0 && userPassword[0] != 0) {
			client.login(userID, userPassword);
			return;
		}
	}

	printf("\nWelcome to %s - %s\n", product, subTitle);
	printf("Do you want to use an existing webCDwriter account (1)\n"
		"or create a new one (2)? ");
	int newAccount;
	while (1) {
		char str[20];
		fgets(str, sizeof str, stdin);
		str[strlen(str) - 1] = 0;
		if (strcmp(str, "1") == 0
			|| strcmp(str, "2") == 0) {
			newAccount = strcmp(str, "2") == 0;
			break;
		}
	}

	if (newAccount) {
		readString("Choose a username: ", userID, sizeof userID);
		char eMail[1024];
		readString("eMail: ", eMail, sizeof eMail);
		client.newAccount(userID, eMail);
		printf("Look for a mail from webCDwriter!\n");
	}
	else
		readString("Username: ", userID, sizeof userID);

	for (int i = 0; ; i++) {
		readPassword("Password: ", userPassword, sizeof userPassword);
		try {
			client.login(userID, userPassword);
			break;
		}
		catch (Error *error) {
			if (i < 2)
				printf("Login failed. Please try again!\n");
			else
				throw error;
		}
	}

	printf("Write the username and the password to %s? (Y/n) ",
		loginFile);
	char str[1024];
	fgets(str, sizeof str, stdin);
	str[strlen(str) - 1] = 0;
	if (str[0] == 0 || strcasecmp(str, "y") == 0)
		writeLoginFile(loginFile, userID, userPassword);
}

int main(int argc, char *argv[]) {
	printf("%s version %s, Copyright (C) 2000-2004 Jörg P. M. Haeger\n",
		product, version);
	printf("\n");

	if (setlocale(LC_CTYPE, "") == NULL) {
		fprintf(stderr, "Cannot set the specified locale!"
			" Check LANG, LC_CTYPE, LC_ALL.\n");
		return 1;
	}

	try {
		CommandArgs args(argc, argv);

		// make sure files and tracks are not mixed
		int files = 0, tracks = 0;
		for (int i = 0; i < args.numOfFiles; i++)
			if (strcmp(args.getType(i), "file") == 0)
				files++;
			else
				tracks++;
		if (files > 0 && tracks > 0)
			throw "Cannot mix files and tracks!";

		printf("Trying to connect to CDWserver...\n");
		Client2 client;
		client.connect(args.host, args.port);
		client.client(product, version);

		struct utsname unameBuf;
		uname(&unameBuf);
		client.system(unameBuf.sysname, unameBuf.release);

		struct passwd *pw = getpwuid(getuid());
		const char *userName;
		if (pw == NULL)
			userName = "";
		else
			userName = pw->pw_name;
		client.user(getuid(), userName);

		client.setProtocol(4);
		if (!client.getAnonymousUse()
			|| args.id[0] != 0 || args.list)
			login(client);
		client.setPrefix(args.prefix);
		if (args.verbose)
			client.setVerbose();

		if (args.list) {
			printf("\vSessions on the server:\n");
			client.listSessions();
			printf("\n");
			return 0;
		}

		int blankTOC = strcmp(args.blank, "fast") == 0;
		if (args.blank[0] != 0)
		if (!blankTOC
			|| (args.id[0] == 0 && args.numOfFiles == 0)) {
			// run cdrecord blank separately
			printf("\nRunning cdrecord blank=%s...\n", args.blank);
			client.blank(args.blank);
			printf("%c", 7);
		}

		printf("\nTrying to open a session...\n");
		if (args.id[0] != 0
				&& args.numOfFiles == 0)
			client.openSession(args.id);
		else
			client.newSession(args.id);

		if (args.numOfFiles > 0) {
			if (args.dir[0] != 0)
				if (chdir(args.dir) != 0)
					throw new Error(
						"Cannot change to %s", args.dir);

			if (args.force)
				client.setForce();

			printf("Transmitting the files...\n");
			for (int i = 0; i < args.numOfFiles; i++)
				if (strcmp(args.getType(i), "file") == 0)
					client.putFile(args.getTrack(i));
				else
					client.putTrack(
						args.getType(i),
						args.getTrack(i));
			printf("%d files (%.3f MB) were transmitted.\n",
				client.numOfFiles,
				client.numOfBytes / 1024.0 / 1024);
			if (client.numOfCannotRead > 0)
				printf("%d unreadable files were ignored.\n",
					client.numOfCannotRead);
			if (client.numOfDoesNotExist > 0)
				printf("%d nonexistent files were ignored.\n",
					client.numOfDoesNotExist);
			printf("\n");
		}

		if (args.numOfFiles > 0 || args.id[0] != 0) {
			client.setFilesystem(
				args.joliet, args.rockRidge, args.hfs);
			client.burnSession(args, blankTOC);
		}
	}
	catch (const char *msg) {
		printf("error: %s\n", msg);
	}
	catch (Error *error) {
		printf("error: %s\n", error->toString());
	}
	printf("%c", 7);

	return 0;
}
