#include "Data.h"

// Author: Steve Talbot

Data:: Data(){

	_w = -1;

	_d = -1;

	_needsToBeFlushedToFile = new vector<bool>();

	_accounts = new vector<AccountInfo*>();

	_currentAccountInfo = NULL;

	_accountFile = new AccountFile();

	_errorMessageIds = new ErrorMessageIds();

	_messageIds = new MessageIds();

	_attempts = -1;

	_maxAttempts = -1;

	_minBalance = -1;

	_overdrawPenalty = -1;

	_errorMessages = new vector<string*>();

	_errorMessage1 = "The user id was invalid.";
	_errorMessage2 = "The user pin that was entered was not found.";
	_errorMessage3 = "The user exceeded the max number of \"pin attempts\".";
	_errorMessage4 = "The \"withdraw\" operation could not be performed.  The current user account balance is overdrawn.";
	_errorMessage5 = "The transaction operation was not performed.  The current user account is inactive.";

	_errorMessages->push_back( &_errorMessage1 );
	_errorMessages->push_back( &_errorMessage2 );
	_errorMessages->push_back( &_errorMessage3 );
	_errorMessages->push_back( &_errorMessage4 );
	_errorMessages->push_back( &_errorMessage5 );

	_messages = new vector<string*>();

	_message1 = "Enter user pin";
	_message2 = "MENU";
	_message3 = "The user account is deactivated.";
	_message4 = "Current account balance";
	_message5 = "The user account is activated.";

	_messages->push_back( &_message1 );
	_messages->push_back( &_message2 );
	_messages->push_back( &_message3 );
	_messages->push_back( &_message4 );
	_messages->push_back( &_message5 );

	_tempId = -1;

	_tempPin = -1;

}


Data:: ~Data(){

	if( _needsToBeFlushedToFile != NULL ) delete _needsToBeFlushedToFile;

	if( _accounts != NULL ) delete _accounts;

	if( _accountFile != NULL ) delete _accountFile;

	if( _errorMessages != NULL ) delete _errorMessages;

	if( _messages != NULL ) delete _messages;

}


bool Data:: addAccountInfo( AccountInfo* account_ ) {

	bool accountInfoAdded = false;

	// each account "id" must be unique ..
	if ( hasAccountInfo( account_->getID() ) == false ) {

		_accounts->push_back( account_ );

		// every account starts as though it is the stable, original version,
		// if this version is changed, the corresponding entry in this
		// vector will toggle to "true" ..
		// (i.e.: "activate_msg()", "deactivate_msg()", "make_deposit()",
		//        "make_withdraw()" ..
		_needsToBeFlushedToFile->push_back( false );

		accountInfoAdded = true;

	}

	return accountInfoAdded;

} // end "addAccountInfo( AccountInfo* account )" ..


bool Data:: removeAccountInfo( int id_ ){

	bool accountInfoRemoved = false;

	int size = _accounts->size();

	// find and remove the first and only instance of this account "id" ..
	for(int i=0; i<size; i++){

		if( _accounts->at(i)->getID() == id_ ){

			_accounts->erase( ( _accounts->begin() + i ) );
			accountInfoRemoved = true;
			break;

		}

	}

	return accountInfoRemoved;

} // end "removeAccountInfo( int id_ )" ..


bool Data:: hasAccountInfo( int id_ ) {

	bool foundAccountInfo = false;

	int size = _accounts->size();

	// find the first and only instance of this account "id" ..
	for(int i=0; i<size; i++){

		if( _accounts->at( i )->getID() == id_ ){

			foundAccountInfo = true;
			break;

		}

	}

	return foundAccountInfo;

} // end "hasAccountInfo( int id_ )" ..


bool Data:: hasFileAccountInfo( int id_ ) {

	bool foundAccountInfo = false;

	foundAccountInfo = _accountFile->hasAccountInfo( id_ );

	return foundAccountInfo;

} // end "hasAccountInfo( int id_ )" ..


 AccountInfo* Data:: getAccountInfo( int id_ ){

	int accountInfoIndex = findAccountIndex( id_ );

 	if( ( accountInfoIndex >= 0 ) &&
 		( accountInfoIndex < _accounts->size() ) ){

 		return _accounts->at( accountInfoIndex );

 	} else {

 		return NULL;

 	}

 } // end "getAccountInfo( int id_ )" ..


 vector<AccountInfo*>* Data:: getAccounts(){

 	return _accounts;

 }


bool Data:: isPinCorrect( int pn_, int id_ ){

	bool isPinCorrect = false;

	if( getIsCurrentAccountFromFile() == true ){

		// "pin" was retrieved from the file ..

		if( getAccountFile()->getAccountInfo()->getPN() == pn_ )
			isPinCorrect = true;

	} else {

		// "pin" is retrieved from the local collection in memory ..

		int accountInfoIndex = findAccountIndex( id_ );

		if( ( accountInfoIndex >= 0 ) &&
 			( accountInfoIndex < _accounts->size() ) ){

			// check the "pin" matching this account "id" ..
			if( _accounts->at( accountInfoIndex )->getPN() == pn_ ){

				isPinCorrect = true;

			}

		}

	}

	return isPinCorrect;

} // end "isPinCorrect( int pn_, int id_ )" ..


/*
 * GETTERS ..
 */

 int Data:: getW(){

 	return _w;

 }

 int Data:: getD(){

 	return _d;

 }

 bool Data:: getNeedsToBeFlushedToFile( int id_ ){

 	// this assumes that "_accounts" and "_needsToBeFlushedToFile"
 	// are both the same "size()" and both non-null ..

	int accountInfoIndex = findAccountIndex( id_ );

 	bool result = false;
	if( ( accountInfoIndex >= 0 ) &&
 		( accountInfoIndex < _needsToBeFlushedToFile->size() ) ){

 		result = _needsToBeFlushedToFile->at( accountInfoIndex );

 	}

 	return result;

 }


 AccountInfo* Data:: getCurrentAccountInfo() {

 	return _currentAccountInfo;

 }

 int Data:: getAttempts(){

 	return _attempts;

 }

 int Data:: getMaxAttempts(){

 	return _maxAttempts;

 }

int Data:: getMinBalance(){

	return _minBalance;

}

int Data:: getOverdrawPenalty(){

	return _overdrawPenalty;

}

vector<string*>* Data:: getErrorMessages(){

	return _errorMessages;

}

string* Data:: getErrorMessage( int position_ ){

	return _errorMessages->at( position_ );

}

string* Data:: getMessage( int position_ ){

	return _messages->at( position_ );

}

int Data:: getTempPin(){

	return _tempPin;

}


 /*
 * SETTERS ..
 */

void Data:: setW( int w_ ){

 	_w = w_;

}

void Data:: setD( int d_ ){

 	_d = d_;

}

void Data:: setNeedsToBeFlushedToFile( int id_, bool needsToBeFlushedToFile_ ){

 	// this assumes that "_accounts" and "_needsToBeFlushedToFile"
 	// are both the same "size()" and both non-null ..

	int accountInfoIndex = findAccountIndex( id_ );

 	if( ( accountInfoIndex >= 0 ) &&
 		( accountInfoIndex < _needsToBeFlushedToFile->size() ) ){

 		_needsToBeFlushedToFile->at( accountInfoIndex ) = needsToBeFlushedToFile_;

 	}

}

void Data:: setCurrentAccountInfo( AccountInfo* currentAccountInfo_ ){

 	_currentAccountInfo = currentAccountInfo_;

}

void Data:: setAttempts( int attempts_ ){

 	_attempts = attempts_;

}

void Data:: setMaxAttempts( int maxAttempts_ ){

	_maxAttempts = maxAttempts_;

}

void Data:: setMinBalance( int minBalance_ ){

 	_minBalance = minBalance_;

}

void Data:: setOverdrawPenalty( int overdrawPenalty_ ){

 	_overdrawPenalty = overdrawPenalty_;

}

void Data:: setErrorMessages( vector<string*>* errorMessages_ ){

 	_errorMessages = errorMessages_;

}

void Data:: setErrorMessage( string* errorMessage_, int position_ ){

	_errorMessages->at( position_ ) = errorMessage_;

}

void Data:: setMessages( vector<string*>* messages_ ){

	_messages = messages_;

}

void Data:: setMessage( string* message_, int position_ ){

	_messages->at( position_ ) == message_;

}


void Data:: setTempPin( int tempPin_ ){

	_tempPin = tempPin_;

}


/*
 * "AccountFile" Wrapper Methods ..
 */


string Data:: getFileDrive(){

	return _accountFile->getFileDrive();

}

string Data:: getFileDirectory(){

	return _accountFile->getFileDirectory();

}

string Data:: getFileName(){

	return _accountFile->getFileName();

}

void Data:: setFileDrive( string fileDrive_ ){

	_accountFile->setFileDrive( fileDrive_ );

}

void Data:: setFileDirectory( string fileDirectory_ ){

	_accountFile->setFileDirectory( fileDirectory_ );

}

void Data:: setFileName( string fileName_ ){

	_accountFile->setFileName( fileName_ );

}

bool Data:: loadAccountInfoFromFile( int id_ ){

	// call method on "AccountFile" object ..
	bool result = _accountFile->loadAccountInfoFromFile( id_ );

	return result;

}

bool Data:: writeAccountInfoToFile( int accountIndex_ ){

	// set the "account info" in the "account file" ..
	_accountFile->setAccountInfo( _accounts->at( accountIndex_ ) );

	// call method on "AccountFile" object ..
	bool result = _accountFile->writeAccountInfoToFile();

	return result;

}

AccountFile* Data:: getAccountFile(){

	return _accountFile;

}

/*
 * Utility methods ..
 */

int Data:: getTempId(){

	return _tempId;

}

void Data:: setTempId( int tempId_ ){

	_tempId = tempId_;

}

bool Data:: getIsCurrentAccountFromFile(){

	return _isCurrentAccountFromFile;

}

void Data:: setIsCurrentAccountFromFile( bool isCurrentAccountFromFile_ ){

	_isCurrentAccountFromFile = isCurrentAccountFromFile_;

}

int Data:: findAccountIndex( int id_ ){

  	int accountInfoIndex = -1;
 	bool accountInfoFound = false;

 	int size = _accounts->size();

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

 		if( _accounts->at(i)->getID() == id_ ){

 			accountInfoIndex = i;
 			accountInfoFound = true;
 			break;

 		}

 	}

 	return accountInfoIndex;

}
