// acctList.cc
// P. Conrad, 4/6/2005 
// list of accounts

#include "acct.h"
#include "acctList.h"
#include <iostream>
using namespace std;

// constructor makes an empty list of accounts

AcctList_C::AcctList_C()
{

#ifdef DEBUG
  cerr << "\nInside default constructor.. this=" << this << endl;
#endif


    numAccounts = 0;
    head = NULL;
    tail = NULL;
}


AcctList_C::~AcctList_C()
{
  // Empty out the current list to recycle memory
  // if we don't do that, we create "garbage" (stuff on heap that 
  // has nothing pointing to it)

#ifdef DEBUG
  cerr << "\nInside destructor.. this=" << this << endl;
  cerr << "Here's list of accounts:" << endl;
  printAllAccounts(cerr);
#endif

  Node *p = head;
  while (p != NULL)
    {
      Node *trailp = p;
      p = p->next;
      delete trailp;
    }
  
  head = tail = NULL; // avoid dangling references
}

// copy constructor traverses the original list making a brand new one
AcctList_C::AcctList_C(const AcctList_C &orig)
{

#ifdef DEBUG
  cerr << "\nInside copy constructor.. &orig=" << &orig << endl;
  cerr << "\nInside copy constructor.. this=" << this << endl;
  cerr << "\nInside copy constructor.. orig=\n" << orig << endl;
#endif


  // start with an empty list
  numAccounts = 0;
  head = tail = NULL;

  // for each item in the original list, make a new node in the
  // new list with matching account information add it to the current list

  for (Node *p=orig.head; p!=NULL; p=p->next)
    addAccount(*(p->acct));
}


// return a reference to the object on the left of the = sign

AcctList_C & AcctList_C::operator=(const AcctList_C & right) // assignment
{

#ifdef DEBUG
  cerr << "\nInside op=.. &right=" << &right << endl;
  cerr << "\nInside op=.. right=" << right << endl;
  cerr << "\nInside op=.. this=\n" << this << endl;
  cerr << "\nInside op=.. *this=\n" << *this << endl;
#endif


  // first, if both sides are the same, do nothing (i.e. a = a)

  if (this == &(right))
    return *this;

  // otherwise, empty out the current list to recycle memory
  // if we don't do that, we create "garbage" (stuff on heap that 
  // has nothing pointing to it)

  Node *p = head;
  while (p != NULL)
    {
      Node *trailp = p;
      p = p->next;
      delete trailp;
    }
    
  // start with an empty list
  numAccounts = 0;
  head = tail = NULL;

  // for each item in the original list, make a new node in the
  // new list with matching account information add it to the current list

  for (Node *p=right.head; p!=NULL; p=p->next)
    addAccount(*(p->acct));

  // finally, return a reference to (*this) to enable chaining

  return (*this);

}

void AcctList_C::addAccount(const Acct_C &a)
{
  Node *p;

  p = new Node;
  p->acct = new Acct_C(a.getAcctNum(), a.getName());
  p->next = NULL;

  if (head==NULL)
    head = tail = p;
  else 
    {
      tail->next = p;
      tail = p;
    }
  numAccounts++;
}


void AcctList_C::printAllAccounts(ostream &out) const
{
  for (Node *p=head; p!=NULL ; p=p->next)
    out << "\t" << p->acct->getAcctNum() 
	 << "\t" << p->acct->getName() << endl;

}



std::ostream & operator << (std::ostream & left, const AcctList_C & right)
{
  right.printAllAccounts(left);
  return left;
}



AcctList_C AcctList_C::operator+(const Acct_C & right)
{
  AcctList_C result(*this); // copy constructor
  result.addAccount(right); // add this account
  return result; // return the result
}










