// Multable Version 0.8
// Coded by William Donaldson
// If you modify this source code,
// please keep these comments intact,
// and create a new comment with
// your information on it.

// If you enjoy this software, please
// feel free to email me and congratulate
// me on my good work! You can email me
// at wdonaldson AT dyo-ecksdee DOT com.
// Knowing people like my software is
// all that I need.

//Changelog
// 0.1 - initial version with interactive capability
// 0.5 - initial public release with support for command line arguments
// 0.6 - adding validation checks for negative numbers, fixed checking for invalid arguments 
// 0.6.1 - fixed NULL warning on invalid argument check
// 0.7 - added "create another table?" question to end of interactive mode
// 0.8 - you can now use tabs instead of spaces to separate columns (-t as first argument on command line)


#include <iostream>
using namespace std;

int interactive(int default_across, int default_down);
int maketable(int across0, int down0, int usetabnotspace);


int main(int argc, char *argv[]) {
	int version_major = 0;
	float version_minor = 8;
	int default_across = 12;
	int default_down = 10;
	int usetabnotspace = 0;
	int quitafter = 0;
	
	if (argc > 1) { // see which arguments are being passed
		int argtype[argc];
		for (int checkarg = 1; checkarg < argc; checkarg++) { //check for arguments
			if (strcmp(argv[checkarg],"-h") == 0) argtype[checkarg] = 1; // set to help argtype
			else if (strcmp(argv[checkarg],"-i") == 0) argtype[checkarg] = 2; // set to interactive argtype
			else if (strcmp(argv[checkarg],"-t") == 0) argtype[checkarg] = 3; // set to use tabs instead of spaces
			else if (!atoi(argv[checkarg])) argtype[checkarg] = 0; // set to be invalid argument
			else argtype[checkarg] = -1; // set to be a number
			switch (argtype[checkarg]) {
				case -1:
					if (argtype[checkarg - 1] != -1) {
						if (checkarg + 1 < argc) {
							if (atoi(argv[checkarg]) >= 0 && atoi(argv[checkarg + 1]) >= 0) {
								if (argtype[checkarg + 1] != -1) {
									maketable(atoi(argv[checkarg]), atoi(argv[checkarg + 1]), usetabnotspace);
								}
							}
							else cout<<"Error: You can't make a multiplication table with negative numbers.\n";
						}
						else cout<<"Error: Please specify two numbers.\n";
					}
					quitafter = 1;
					break;					
				case 1:
					cout<<"Multable v"<<version_major<<"."<<version_minor<<"\n";
					cout<<"Usage: "<<argv[0]<<" [-hit] [across] [down]\n";
					cout<<"Arguments:\n";
					cout<<"	-h		Show Help\n";
					cout<<"	-i		Interactive Mode\n";
					cout<<"	-t		Use Tabs between Columns (use as first argument)\n";
					quitafter = 1;
					break;
				case 2:
					interactive(default_across, default_down);
					quitafter = 1;
					break;
				case 3:
					usetabnotspace = 1;
					break;
				default:
					cout<<"Error: "<<argv[checkarg]<<": Unknown argument\n";
					break;
			}
		}
	}
	
	if (quitafter == 1) return 0;
	else {
		maketable(default_across, default_down, usetabnotspace);
		return 0;
	}

}

int interactive(int _across, int _down) {
	int quit = 0;
	int usetabnotspace;
	char ust;
	do {
		int across;
		int down;
		char which;		
		
		
		cout<<"Use defaults (across = "<<_across<<", down = "<<_down<<")? (y/n) ";
		cin>>which;
		
		if (which == 'n') {
			int dy = 0;
			for (dy = 0; dy != 1; dy = dy) {
				cout<<"Input the amount you want across. ";
				cin>>across;
				if (across < 0) cout<<"Error: You can't make a multiplication table with negative numbers.\n";
				else dy = 1;
			}
			for (dy = 0; dy != 1; dy = dy) {
				cout<<"Input the amount you want down. ";
				cin>>down;
				if (down < 0) cout<<"Error: You can't make a multiplication table with negative numbers.\n";
				else dy = 1;
			}
			for (dy = 0; dy != 1; dy = dy) {
				cout<<"Would you like to use tabs instead of spaces? (y/n) ";
				cin>>ust;
				if (ust != 'y' || ust != 'n') cout<<"Error: Not a valid response\n";
				else {
					if (ust == 'y') usetabnotspace = 1;
					else if (ust == 'n') usetabnotspace = 0;
					dy = 1;
				}
			}
		}
		else {
			across = _across;
			down = _down;
		}

		cout<<"Outputting "<<across<<" rows, "<<down<<" columns.\n\n";
		
		maketable(across, down, usetabnotspace);
		
		cout<<"\n";
		char another;
		for (int isdone = 0; isdone != 1; isdone = isdone) {
			cout<<"Create another table? (y/n) ";
			cin>>another;
			if (another == 'n') {
				quit = 1;
				isdone = 1;
			}
			else if (another == 'y') {
				quit = 0;
				isdone = 1;
			}
			else cout<<"Error: Not a valid response\n";
		}
	} while (quit != 1);

	return 0;
}

int maketable(int across0, int down0, int usetabnotspace) {
	int maxchar = 1;
	int maxcharmult = 10;
	if (usetabnotspace != 1) {
		for (maxchar = 1, maxcharmult = 10; across0 * down0 > maxcharmult; maxchar = maxchar + 1, maxcharmult = maxcharmult * 10);
	}
	
	/* create table */
	int out; // create holder for number
	for (int down1 = 0; down1 <= down0; down1++) { // make a column
		for (int across1 = 0; across1 <= across0; across1++) { // fill column in rows
			if (across1 == 0) {
				out = down1;
			}
			else if (down1 == 0) {
				out = across1;
			}
			else {
				out = across1 * down1;
			}
			cout<<out;
			
			if (usetabnotspace != 1) {
				int charspernum = 1;
				int multmax = 10;
	
				for (charspernum = 1, multmax = 10; out >= multmax; charspernum = charspernum + 1, multmax = multmax * 10);
				int hms = maxchar - charspernum + 1;
				for (int space = 1; space <= hms; space++) cout<<" ";
			}
			else cout<<"	";
			
		}
		cout<<"\n";
	}
	return 0;
}
