#include <iostream>
using namespace std;

//This is a project that allos the user to add, delete, modify or print users in the system and also be able to print out the user database.

class AccountInfo
{
private:
	char* _userLoginName; // store the login name of the user
	char* _password; // explained later
	unsigned int _uid; //user identifier
	unsigned int _gid; // identifier of user’s primary group
	char* _gecos; // general info of the user
	char* _home; // home directory of the user
	char* _shell; // shell of the user
	// other private methods necessary for this class
public:
	AccountInfo();
	AccountInfo(char [], char [], int, int, char [], char [], char []);

	// constructors(empty and non-empty), destructor
	// ostream operator<<
	//	output to ostream using the following format 
	//
	//	Login: [_userLoginName]
	//	Directory: [_home]
	//	Shell: [_shell]
	//	Gecos: [_gecos]
	//
	// and other public methods (mutators/setters, accessors/getters)
};

AccountInfo::AccountInfo(){
	_userLoginName = new char[9];
	_password = new char[17];
	_uid;
	_gid;
	_gecos;
	_home;
	_shell;
}
AccountInfo::AccountInfo(char userLoginName[], char password[], int uid, int gid, char gecos[], char home[], char shell[]){
	_userLoginName = userLoginName;
	_password = password;
	_uid = uid;
	_gid = gid;
	_gecos = gecos;
	_home = home;
	_shell = shell;
}

class UserDB
{
private:
	AccountInfo* _accounts[200]; // store up to 200 accounts
	unsigned int _size; // number of account stored
	unsigned int _nextUid; // next user id to be assigned
	unsigned int _defaultGid; // default group id
	// other private methods necessary for this class
public:
	// constructors(empty), destructor
	// Note: since the objects stored in _accounts are dynamically
	// allocated, you need delete the objects stored in it in
	// the destructor
	// ostream operator<< // print users in ‘/etc/passwd’ format
	// for the fields that are missing,
	// don’t print out anything. The only
	// exception is ‘x’ will be shown if
	// password is not set.
	void adduser( AccountInfo* newUser); // add a new user to
	//	_accounts, also increment _size.
	// print out the following message after the
	// user is added:
	// “[userLoginName] with	[uid]	is added.”
	void	showUsers();
	//	print out “List of users:” at the first line, then print out all user login names
	//	(one line each user login name), then print out the following at the end according to the number of users stored
	//	0 => “There’s no users found in the system.”
	//	1 => “1 user found in the system.”
	// k => “k users found in the system.” for k>1
	void	showPasswd(); // call the ostream operator
	void	finger(char* userLoginName);	// call ostream operator of AccountInfo class
	int	size();	// return the number of accounts stored	(_size)
	// and other public methods (mutators/setters, accessors/getters)
};

void emptyString(char* token, int size) {
	for (int i=0; i < size; i++) token[i] = '\0';
}

void setDefaults(char uloginName[], char *home_directory, char *password, char *shell, char *gecos) {
	emptyString(home_directory, sizeof(home_directory) - 1);
	strcpy(home_directory, "home/home/");
	strcat(home_directory, uloginName);

	//emptyString(password, sizeof(password) - 1);
	
	//emptyString(shell, sizeof(shell) - 1);

	//shell = "/bin/bash";
	//cout << sizeof(shell) << endl;

	//emptyString(gecos, sizeof(gecos) - 1);
}

int getNextToken(char* buffer, char* token, int startPos, int bufSize, int tokenSize, char delimeter)
{
	int i, j;

	emptyString (token, tokenSize);

	i = startPos;
	j = 0;

	while ((buffer[i] == ' ') && (i < bufSize)) i++; //skipblanks
	if (i < 256) {
		while ((buffer[i] != delimeter) && (i < 256) && (j < tokenSize))
			token[j++] = buffer[i++];
	}
	return i;
}

int main()
{
	char buffer[256];
	AccountInfo *tempAccount;
	UserDB users;
	char uloginName[9];
	char homeDirectory[33];
	int userID;
	int groupID;
	char password[17];
	char shell[17];
	char gecos[65];
	int i, j, k;
	char flag[3];
	char IDString[6];
	char command[11];
	char blank = ' ';

	//	Then add it to “users” by calling adduser(...)
	// if it is a “finger” command, print out the account info for // he specified user using the ostream operator of AccountInfo
	// if it is “showusers”, print out all the users using the // ostream operator of UserDB class. (call showUsers() )
	// if it is “showpasswd”, print out all the users in /etc/passwd // format using the print_passwd() method of UserDB class // (call showPasswd())
	// consume all the white spaces ( such as ‘\n’, ‘\r’ ...)
	while (!cin.eof()) {
		cin.getline(buffer,256);
		cout << buffer << endl;
		k = getNextToken(buffer,command,0,256,10,blank);
		switch(command[0]) {
		case 'a': {
			cout << "Add User" << endl;
			k = getNextToken(buffer, uloginName,k,256,8, blank);
			cout << "****** " << uloginName << endl;
			while (k < 256) {
				k = getNextToken(buffer,flag,k,256,2, blank);
				if (k < 256) {
					userID = 0;
					groupID = 0;
					setDefaults(uloginName, homeDirectory, password, shell, gecos);
					switch (flag[1]) {
					case 'd': k = getNextToken(buffer,homeDirectory,k,256,32, blank);
						cout << "****** " << flag << endl;
						cout << "****** " << homeDirectory << endl;
						break;
					case 's': k = getNextToken(buffer,shell,k,256,16, blank);
						cout << "****** " << flag << endl;
						cout << "****** " << shell << endl;
						break;
					case 'p': k = getNextToken(buffer,password,k,256,16, blank);
						cout << "****** " << flag << endl;
						cout << "****** " << password << endl;
						break;
					case 'c': k = getNextToken(buffer,gecos,k,256,64, '-');
						cout << "****** " << flag << endl;
						cout << "****** " << gecos << endl;
						break;
					case 'u': k = getNextToken(buffer,IDString,k,256,5, blank);
						userID = atoi(IDString);
						cout << "****** " << flag << endl;
						cout << "****** " << IDString << "=" << userID << endl;
						break;
					case 'g': k = getNextToken(buffer,IDString,k,256,5, blank);
						groupID = atoi(IDString);
						cout << "****** " << flag << endl;
						cout << "****** " << IDString << "= " << groupID << endl;
						break;
					default: k = 256; break;
					} //end Switch(flag[1])
				} // end while (k < 256)
			}
			break;
				  } //end of adduser
		case '#': {cout << "Comment" << endl; break;}
		case 's': {
			if (command[4] == 'u') {
				cout << "Show users" << endl;
			}
			else if (command[4] = 'p') {
				cout << "Show password" << endl;
			}
			break;}
		case 'f': {cout << "finger" << endl; break;}
		default: cout << "Command not found!!" << endl;
		}
	}
	return 0;
}