/*	AccountClass class implementation */

#include <iostream.h>
#include <lvpvector.h>
#include <lvpstring.h>

using namespace std;	// October 5, 2001

//--------------------------------------------------------------------------------
AccountClass::AccountClass()
	: Balance(0), TransDates(0), TransKinds(0), TransAmts(0), IsOpen(false)
{
}
//--------------------------------------------------------------------------------
AccountClass::AccountClass(lvpstring AcctName, DateClass AcctOpenDate)
	: Name(AcctName), OpenDate(AcctOpenDate), Balance(0),
	TransDates(0), TransKinds(0), TransAmts(0), IsOpen(true)
/* Opens AcctName account on AcctOpenDate with 0 balance */
{
}
//--------------------------------------------------------------------------------
void AccountClass::SpecifyAccount(lvpstring AcctName, 
		DateClass AcctOpenDate)
/*	Assigns AcctName and AcctOpenDate to account if account not initialized
	Post: AcctName assigned to Name and AcctOpenDate assigned to
	OpenDate if account was not already initialized. IsOpen is true.               */
{
	if (!IsOpen) {
		Name = AcctName;
		OpenDate = AcctOpenDate;
		IsOpen = true;
	}
}

//--------------------------------------------------------------------------------
bool AccountClass::Deposit(double Amt, DateClass Date)
/*	Post: If account open, adds Amt to Acct, records transaction, 
	and returns true; returns false otherwise.                                */
{
	if (IsOpen) {
		Balance += Amt;
		AddTransaction("Deposit", Date, Amt);
		return(true);
	}
	else
		return(false);
}
//--------------------------------------------------------------------------------
bool AccountClass::Withdrawal(double Amt, DateClass Date)
/*	Post: if Amt<=Balance, Amt deleted from account,
	transaction recorded, and true returned. Otherwise, false returned, 
	attempt recorded, and balance unchanged.                                        */
{
	if (Amt <= Balance) {
		Balance -= Amt;
		AddTransaction("Withdrawal", Date, Amt);
		return(true);
	}
	else {
		AddTransaction("Withdrawal/Failed", Date, Amt);
		return(false);
	}
}
//-------------------ACCESS FUNCTIONS---------------------------------
double AccountClass::GetBalance() const //Returns current balance
{ return (Balance); }
lvpstring AccountClass::GetName() const
{ return (Name); } 
DateClass AccountClass::GetOpenDate() const
{ return (OpenDate); }
int AccountClass::GetTransCount() const //Returns number of trans
{ return (TransDates.length()); }
DateClass AccountClass::GetTransDate(int TransNum) const
{ return (TransDates[TransNum]); }
lvpstring AccountClass::GetTransKind(int TransNum) const
{ return (TransKinds[TransNum]); }
double AccountClass::GetTransAmt(int TransNum) const
{ return (TransAmts[TransNum]); }
//--------------------------------------------------------------------------------
void AccountClass::WriteTransactions(ostream & OutFile) const
/*	Writes transactions to OutFile
	Post: All information about the account written to OutFile,
	including a list of all transactions.                                         */
{
	OutFile.setf(ios::fixed);
	OutFile.precision(2);
	OutFile << Name << endl;
	OutFile << "Acct opened on " << OpenDate << " Balance: "
	<< Balance << endl;
	OutFile << "Transactions" << endl;
	for (int i=0; i<TransDates.length(); i++) {
		OutFile.width(12); OutFile << TransDates[i];
		OutFile.width(22); OutFile << TransKinds[i];
		OutFile.width(12); OutFile << TransAmts[i] << endl;
	}
}
//--------------------------------------------------------------------------------
void AccountClass::AddTransaction(lvpstring Kind, DateClass Date,
	double Amt)
/*	Records transaction in appropriate position of arrays by date
	Post: Transaction recorded in appropriate position by date      */
{
	int NewSize = TransDates.length() + 1; 
	TransDates.resize(NewSize);
	TransKinds.resize(NewSize);
	TransAmts.resize(NewSize);
	int NewSpot = NewSize - 2; 
	while ((NewSpot >= 0) && (TransDates[NewSpot] > Date)) {
		TransDates[NewSpot+1] = TransDates[NewSpot];
		TransKinds[NewSpot+1] = TransKinds[NewSpot];
		TransAmts[NewSpot+1] = TransAmts[NewSpot];
		NewSpot--;
	}
	TransDates[NewSpot+1] = Date;
	TransKinds[NewSpot+1] = Kind;
	TransAmts[NewSpot+1] = Amt;
}
//--------------------------------------------------------------------------------
void AccountClass::Store(ostream & OutFile) const
/*	Pre: InFile is open
	Post: Account written in standard format to OutFile */
{
	OutFile << Name << endl;
	OutFile << OpenDate << endl;
	OutFile << Balance << endl;
	OutFile << TransDates.length() << endl;
	for (int TransNum = 0; TransNum < TransDates.length(); TransNum++) {
		OutFile << TransDates[TransNum] << endl;  
		OutFile << TransKinds[TransNum] << endl;  
		OutFile << TransAmts[TransNum] << endl;
	}
}
//--------------------------------------------------------------------------------
void AccountClass::Retrieve(istream & InFile)
/*	Pre: InFile is open and positioned at a properly formatted account
	Post: Next account has been read from InFile into account              */
{
	getline(InFile, Name);
	OpenDate.Read(InFile);
	InFile >> Balance; InFile.ignore(80,'\n');
	int TransCount;
	InFile >> TransCount; InFile.ignore(80,'\n');
	TransDates.resize(TransCount);
	TransKinds.resize(TransCount);
	TransAmts.resize(TransCount);
	for (int TransNum = 0; TransNum < TransCount; TransNum++) {
		InFile >> TransDates[TransNum];
		getline(InFile, TransKinds[TransNum]);
		InFile >> TransAmts[TransNum]; InFile.ignore(80,'\n');
	}
	IsOpen = true;
}

