#include <iostream>

#include "List.h"

#if !defined(_RWSTD_NO_NAMESPACE)
using namespace std;
#endif

// instantiate a class EZTools object for each persistent class
EZTOOLS(IntListNode,i1) ;
EZTOOLS(IntList,i2) ;

IntListBase::~IntListBase()
{
  cout << "Bye from IntListBase" << endl;
}

IntListNode::~IntListNode()
{
  cout << "Bye from IntListNode - Int Value = " << m_Data << endl;
}

void IntListNode::PrintIntListNode() const
{
  cout << "Int Value(multiplicity) = " << m_Data << "(" << m_RepeatValue << ")"
       << " : Node Address = " << this << endl;
}

IntList::IntList()
{
  EZUniverse *pCurrentUniverse = EZUniverse::GetCurrentUniverse();
  if(!pCurrentUniverse->InProcessOfRestoringUniverse())
    m_pHeadNode = 0;
}

IntList::~IntList()
{
  EZPtr<IntListNode> ptr1 = m_pHeadNode, ptr2;

  while(ptr1 != 0)
  {
    ptr2 = ptr1->m_pNextIntListNode;
    EZDelete(ptr1);
    ptr1 = ptr2;
  }

  cout << "Bye from IntList" << endl;
}

void IntList::vInsertInIntList(int data)
{
  if(m_pHeadNode == 0)
  {
    m_pHeadNode = EZNew(IntListNode)(data);
    return;
  }

  EZPtr<IntListNode> pPrevious(0), pCurrent = m_pHeadNode, pNew(0);

  while(pCurrent != 0)
  {
    if(data == pCurrent->m_Data)
    {
      ++pCurrent->m_RepeatValue;
      return;
    }
    else if(data < pCurrent->m_Data)
    {
      break;
    }
    else
    {
      pPrevious = pCurrent;
      pCurrent = pCurrent->m_pNextIntListNode;
    }
  }

  pNew = EZNew(IntListNode)(data);

  if(pPrevious == 0)
  {
    pNew->m_pNextIntListNode = m_pHeadNode;
    m_pHeadNode = pNew;
  }
  else
  {
    pNew->m_pNextIntListNode = pPrevious->m_pNextIntListNode;
    pPrevious->m_pNextIntListNode = pNew;
  }
}

void IntList::vDeleteFromIntList(int data)
{
  if(m_pHeadNode == 0)
    return;

  EZPtr<IntListNode> pPrevious(0), pCurrent = m_pHeadNode;

  while(pCurrent != 0)
  {
    if(data == pCurrent->m_Data)
    {
      if(pCurrent->m_RepeatValue > 1)
        --pCurrent->m_RepeatValue;
      else
      {
        if(pPrevious == 0)
        {
          m_pHeadNode = m_pHeadNode->m_pNextIntListNode;
          EZDelete(pCurrent);
        }
        else
        {
          pPrevious->m_pNextIntListNode = pCurrent->m_pNextIntListNode;
          EZDelete(pCurrent);
        }
      }

      return;
    }

    pPrevious = pCurrent;
    pCurrent = pCurrent->m_pNextIntListNode;
  }
}

void IntList::vPrintIntList() const
{
  cout << "***** Print Int List (begin) *****" << endl;

  if(m_pHeadNode == 0)
  {
    cout << "IntList is Empty" << endl;
    return;
  }

  EZPtr<IntListNode> pIntListNode = m_pHeadNode;

  while(pIntListNode != 0)
  {
    pIntListNode->PrintIntListNode();
    pIntListNode = pIntListNode->m_pNextIntListNode;
  }

  cout << "***** Print Int List (end) *****" << endl;
}
