/*=========================================================================

  Copyright (c) Kitware, Inc.
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/VolViewCopyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkQueue.txx"
#include "vtkQueueIterator.txx"
#include "vtkLinkedList.txx"
#include "vtkActor.h"
#include "vtkMath.h"

#define ABS(x) ((x)<0?-(x):(x))

int main()
{
  int cc;
  int res =0;
  vtkQueue<vtkActor*> *aq;
  /*
  const int count = 60;

  vtkQueue<int>* q = vtkQueue<int>::New();
  for ( cc = 0; cc < count; cc ++ )
    {
    //cout << "Queue size: " << q->GetNumberOfItems() << " / " << q->GetSize()<< endl;
    if ( q->EnqueueItem(cc) != VTK_OK )
      {
      cout << "Cannot enqueue item: " << cc << endl;
      res = 1;
      }
    //q->DebugList();
    // cout << "Queue size: " << q->GetSize() << endl;
    }

  //q->DebugList();
  for ( cc = 0; cc < count-1; cc ++ )
    {
    int i;
    //q->DebugList();
    if ( q->GetDequeueItem(i) == VTK_OK )
      {
      if ( cc != i )
        {
        //q->DebugList();
        cout << "Wrong item dequeued. Expected: " << cc << " got " << i << endl;
        res = 1;
        }
      //cout << "Got: " << i << endl;
      }
    else
      {
      cout << "Cannot access item: " << cc << endl;
      }
    if ( q->DequeueItem() != VTK_OK )
      {
      cout << "Cannot dequeue item: " << cc << endl;
      res = 1;
      }
    //q->DebugList();
    }
  for ( cc = 0; cc < count+3; cc ++ )
    {
    //cout << "Queue size: " << q->GetNumberOfItems() << " / " << q->GetSize()<< endl;
    if ( q->EnqueueItem(cc) != VTK_OK )
      {
      cout << "Cannot enqueue item: " << cc << endl;
      res = 1;
      }
    //q->DebugList();
    //cout << "Queue size: " << q->GetSize() << endl;
    }
  for ( cc = 0; cc < 10; cc ++ )
    {
    int i;
    int jj;
    for ( jj = 0; jj < 3; jj ++ )
      {
      if ( q->EnqueueItem(cc*3 + jj) != VTK_OK )
        {
        cout << "Cannot enqueue item: " << cc << endl;
        res = 1;
        }
      }
    for ( jj = 0; jj < 3; jj ++ )
      {
      if ( q->GetDequeueItem(i) != VTK_OK )
        {
        if ( i != cc*3 + jj )
          {
          cout << "Wrong item dequeued. Expected: " << cc*3+jj << " got " << i << endl;
          res = 1;
          }
        }
      if ( q->DequeueItem() != VTK_OK )
        {
        cout << "Cannot dequeue item: " << cc*3+jj << endl;
        res = 1;
        }
      }
    }
  cout << "Final size: " << q->GetSize() << endl;
  q->Delete();

  aq = vtkQueue<vtkActor*>::New();
  for ( cc = 0; cc < 5; cc ++ )
    {
    vtkActor* a = vtkActor::New();
    aq->EnqueueItem(a);
    //cout << "Enqueue: " << a << endl;
    a->Delete();
    }
  vtkQueueIterator<vtkActor*> *it = aq->NewQueueIterator();
  for ( it->InitTraversal(); !it->IsDoneWithTraversal(); it->GoToNextItem() )
    {
    vtkActor* a = 0;
    vtkIdType key = 0;
    if ( it->GetData(a) != VTK_OK || !a )
      {
      cout << "Problem accessing element from the queue with iterator" << endl;
      res = 1;
      aq->DebugList();
      }
    if ( it->GetKey(key) != VTK_OK )
      {
      cout << "Problem accessing key from the queue with iterator" << endl;
      res = 1;
      }
    //cout << "Accessing element, got: " << a  << " (key " << key << ")"<< endl;
    }
  it->Delete();
  for ( cc = 0; cc < 5; cc ++ )
    {
    vtkActor* a;
    if ( aq->GetDequeueItem(a) != VTK_OK )
      {
      cout << "Cannot get actor from the queue: " << cc << endl;
      res = 1;
      }
    if ( a )
      {
      a->Register(0);
      }
    if ( aq->DequeueItem() != VTK_OK )
      {
      cout << "Cannot dequeue actor " << cc << endl;
      res =1;
      }
    if ( a )
      {
      a->UnRegister(0);
      }
    }
  aq->Delete();
  */
  const int total_count = 10000;
  
  aq = vtkQueue<vtkActor*>::New();
  vtkLinkedList<vtkActor*> *all = vtkLinkedList<vtkActor*>::New();
  for ( cc = 0; cc < total_count; cc ++ )
    {
    float f = vtkMath::Random(-1, 1);
    if ( ABS(f) < .0005 )
      {
      while( aq->GetNumberOfItems() > 0 )
        {
        vtkActor* acq = 0;
        vtkActor* acll = 0;
        if ( aq->GetDequeueItem(acq) != VTK_OK )
          {
          cout << "Cannot get dequeue item" << endl;
          res = 1;
          }
        if ( all->GetItem(0, acll) != VTK_OK )
          {
          cout << "Cannot get first item from linked list" << endl;
          res = 1;
          }
        if ( acq != acll )
          {
          cout << "Items are not the same: " << acq << " <> " << acll << endl;
          res = 1;
          }
        if ( aq->DequeueItem() != VTK_OK )
          {
          cout << "Cannot dequeue item" << endl;
          res = 1;
          }
        if ( all->RemoveItem(0) != VTK_OK )
          {
          cout << "Cannot remove item from linked list" << endl;
          res = 1;
          }
        }
      }
    else if ( f < 0 )
      {
      // Enqueue
      vtkActor* a = vtkActor::New();
      aq->EnqueueItem(a);
      all->AppendItem(a);
      a->Delete();
      }
    else
      {
      // Dequeue
      if ( all->GetNumberOfItems() > 0 || aq->GetNumberOfItems() > 0 )
        {
        vtkActor* acq = 0;
        vtkActor* acll = 0;
        if ( aq->GetDequeueItem(acq) != VTK_OK )
          {
          cout << "Cannot get dequeue item" << endl;
          res = 1;
          }
        if ( all->GetItem(0, acll) != VTK_OK )
          {
          cout << "Cannot get first item from linked list" << endl;
          res = 1;
          }
        if ( acq != acll )
          {
          cout << "Items are not the same: " << acq << " <> " << acll << endl;
          aq->DebugList();
          res = 1;
          }
        if ( aq->DequeueItem() != VTK_OK )
          {
          cout << "Cannot dequeue item" << endl;
          res = 1;
          }
        if ( all->RemoveItem(0) != VTK_OK )
          {
          cout << "Cannot remove item from linked list" << endl;
          res = 1;
          }
        }
      }
    }

  cout << "Number of elements left in queue: " << aq->GetNumberOfItems() << " / " << aq->GetSize() << endl;
  cout << "Number of elements left in linked list: " << aq->GetNumberOfItems() << endl;
  aq->Delete();
  all->Delete();
  
  if ( res )
    {
    cout << "Errors" << endl;
    }

  return res;
}
