// select an account to be the active account
void SelectActiveAccount(){
	ViewAccounts();
	int maxID = DB.GetMaxField(ACCOUNT_TABLE, "AcctID");
	int selID = GetUserInput("Select an account ID", maxID);
	stringstream is("");
	is<<selID;
	if(!validate::string::numeric(is.str())){
		cout << "invalid id";
		return;
	}
	ActiveAccountID=selID;
	cout << "Active account selected.";
	return;
}
// select the profile to be the active profile
void SelectActiveProfile(){
	ViewProfiles(); 
	int maxID = DB.GetMaxField(USER_TABLE, "UserID");
	int selID = GetUserInput("Select a profile ID", maxID);
	stringstream is("");
	is<<selID;
	if(!validate::string::numeric(is.str())){
		cout << "invalid id";
		return;
	}
	ActiveUserID=selID;
	cout << "Active profile selected.";
	return;
}
// get user prompts for table fields and add a new row
// to a table, with an auto-incremented id. 
void CreateInTable(TableDefinition Def, char* Table, char* key){
	
	string name, val;
	
	DB.UseTableDefinition(Def);
	//cout << "key: " << key;

	TableRow Columns = DB.GetColumnsForTable(Table); // get all the columns
	TableDataSet NewDataSet;

	for(unsigned int i=0; i<Columns.size(); i++){

		if(Columns[i] == key){
		 
			 int maxID = DB.GetMaxField(Table, key);
			 int newID = maxID+1;

			 stringstream ID("");
			 ID << newID;

			 NewDataSet.push_back(make_pair(key, (char*)ID.str().c_str()));
		}
		else{

			cout << Columns[i] << ": ";
		
			getline(cin, val);
		
			FieldDefinition WorkingFieldDefinition = DB.GetFieldDefinition((char*)Columns[i].c_str());

			if((WorkingFieldDefinition.getLength() > 0) && (WorkingFieldDefinition.Validate((char*)val.c_str()))){
				NewDataSet.push_back(make_pair(Columns[i],val));
			}
			else{
				cout << "validation failed for the field " << WorkingFieldDefinition.getName();
				return;
			}
		}
	}

	DB.Create(Table, NewDataSet);
	DB.ShowTable(Table, NewDataSet);
	return;
}
// delete a profile
void DeleteProfile(){
	TableDataSet NewDataSet;
	
	stringstream is("");
	ViewProfiles();
	
	is << GetUserInput("Select an ID to delete", DB.GetMaxField(USER_TABLE, "UserID"));
	
	if(!validate::string::numeric(is.str())){
		cout << "invalid id";
		return;
	}

	NewDataSet.push_back(make_pair("UserID", is.str().c_str()));
	
	DB.Delete(USER_TABLE, NewDataSet);
	
	ActiveUserID=-1;
}
// delete an account
void DeleteAccount(){
	
	TableDataSet NewDataSet;
	
	stringstream is("");
	
	ViewAccounts();
	
	is << GetUserInput("Select an ID to delete", DB.GetMaxField(ACCOUNT_TABLE, "AcctID"));
	
	NewDataSet.push_back(make_pair("AcctID", is.str()));
	DB.Delete(ACCOUNT_TABLE, NewDataSet);
	
	// delete transactions matching this user and account id
	TableDataSet TransactionTableDataSet;
	stringstream AAID(""); // active account id
	stringstream AUID(""); // active user id

	AAID << ActiveAccountID;
	AUID << ActiveUserID;

	if(DB.FieldExists(USER_TABLE, "UserID", (char*)AUID.str().c_str()) == false){
		ActiveUserID = -1;
		cout << "User ID selected does not exist.";
		return;
	}
	else if(DB.FieldExists(ACCOUNT_TABLE, "AcctID", (char*)AAID.str().c_str()) == false){
		ActiveAccountID = -1;
		cout << "Account ID selected does not exist.";
		return;
	}
	
	TransactionTableDataSet.push_back(make_pair("AcctID", AAID.str().c_str()));
	TransactionTableDataSet.push_back(make_pair("UserID", AUID.str().c_str()));

	DB.Delete(TRANSACTION_TABLE, TransactionTableDataSet);

	ActiveAccountID = -1;
}
// add a transaction to the table.
void TransactAmount(bool isCredit){

	if(isCredit){
		cout << "Deposit" << endl;
	}
	else{
		cout << "Withdraw" << endl;
	}

	stringstream AAID(""); // active account id
	stringstream AUID(""); // active user id
	stringstream TNUM(""); // transaction number
	stringstream TAMT(""); // transaction amount
	stringstream DATE(""); // timestamp
	stringstream NBAL(""); // updated balance

	// create a new transaction id
	int TransNum = DB.GetMaxField(TRANSACTION_TABLE, "TransNum");
	int newTransNum = TransNum+1;

	// get the transaction amount
	double transAmt = GetUserInput("Enter Transaction Amount", INT_MAX);

	stringstream sM("");
	sM << transAmt;

	// validation. Minimal validation. Better than nothing.

	if(!validate::string::money(sM.str())){
		cout << "that does not appear to be a valid monetary amount.";
		return;
	}
	
	AAID << ActiveAccountID;
	AUID << ActiveUserID;

	if(!validate::string::numeric(AAID.str())){
		ActiveAccountID = -1;
		cout << "The account id is invalid. " << endl;
		return;
	}

	if(!validate::string::numeric(AUID.str())){
		ActiveUserID = -1;
		cout << "the user id is invalid. " << endl;
		return;
	}

	stringstream clause("");
	
	// this is terrible, but it works. 
	clause << " UserID = '" << ActiveUserID << "' and AcctID = '" << ActiveAccountID << "' ";
	
	double exSum = DB.GetSumField(TRANSACTION_TABLE, "TransAmount", (char*)clause.str().c_str());
	
	TNUM << newTransNum;
	
	DATE << time(0);

	if(isCredit){
		TAMT << transAmt;
		NBAL << (exSum+transAmt);
	}
	else{
		TAMT << "-" << transAmt;
		NBAL << (exSum-transAmt);
	}
	
	TableDataSet NewDataSet;
	NewDataSet.push_back(make_pair("AcctID",      AAID.str().c_str()));
	NewDataSet.push_back(make_pair("UserID",      AUID.str().c_str()));
	NewDataSet.push_back(make_pair("TransNum",    TNUM.str().c_str()));
	NewDataSet.push_back(make_pair("TransAmount", TAMT.str().c_str()));
	NewDataSet.push_back(make_pair("TransDate",   DATE.str().c_str()));
	NewDataSet.push_back(make_pair("Balance",     NBAL.str().c_str()));
	
	DB.Create(TRANSACTION_TABLE, NewDataSet);
	DB.ShowTable(TRANSACTION_TABLE, NewDataSet, 2); 
}