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

  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 "vtkVVSnapshotPool.h"

#include "vtkObjectFactory.h"
#include "vtkVVSnapshot.h"

#include <vtksys/stl/vector>

//---------------------------------------------------------------------------
vtkStandardNewMacro(vtkVVSnapshotPool);
vtkCxxRevisionMacro(vtkVVSnapshotPool, "$Revision: 1.5 $");

#ifdef KWCommonPro_USE_XML_RW
#include "XML/vtkXMLVVSnapshotPoolReader.h"
#include "XML/vtkXMLVVSnapshotPoolWriter.h"
#endif
vtkKWGetXMLReaderWriterObjectsImplementationMacro(vtkVVSnapshotPool, vtkXMLVVSnapshotPoolReader, vtkXMLVVSnapshotPoolWriter);

//----------------------------------------------------------------------------
class vtkVVSnapshotPoolInternals
{
public:

  // Snapshots

  typedef vtksys_stl::vector<vtkVVSnapshot*> SnapshotPoolType;
  typedef vtksys_stl::vector<vtkVVSnapshot*>::iterator SnapshotPoolIterator;
  SnapshotPoolType SnapshotPool;
};

//----------------------------------------------------------------------------
vtkVVSnapshotPool::vtkVVSnapshotPool()
{  
  this->Internals = new vtkVVSnapshotPoolInternals;
}

//----------------------------------------------------------------------------
vtkVVSnapshotPool::~vtkVVSnapshotPool()
{
  // Delete our pool

  if (this->Internals)
    {
    this->RemoveAllSnapshots(); // Note that this call this->Initialize()
    delete this->Internals;
    }
}

//----------------------------------------------------------------------------
int vtkVVSnapshotPool::GetNumberOfSnapshots()
{
  if (this->Internals)
    {
    return (int)this->Internals->SnapshotPool.size();
    }

  return 0;
}

//----------------------------------------------------------------------------
vtkVVSnapshot *vtkVVSnapshotPool::GetNthSnapshot(int i)
{
  // Get the ith snapshot

  if (i < 0 || i >= this->GetNumberOfSnapshots() || !this->Internals)
    {
    vtkErrorMacro("Index out of range");
    return NULL;
    }
  
  return this->Internals->SnapshotPool[i];
}

//----------------------------------------------------------------------------
int vtkVVSnapshotPool::HasSnapshot(vtkVVSnapshot *snapshot)
{
  if (snapshot)
    {
    vtkVVSnapshotPoolInternals::SnapshotPoolIterator it = 
      this->Internals->SnapshotPool.begin();
    vtkVVSnapshotPoolInternals::SnapshotPoolIterator end = 
      this->Internals->SnapshotPool.end();
    for (; it != end; ++it)
      {
      if ((*it) == snapshot)
        {
        return 1;
        }
      }
    }
  return 0;
}

//----------------------------------------------------------------------------
int vtkVVSnapshotPool::GetIndexOfSnapshot(vtkVVSnapshot *snapshot)
{
  int r = 0;
  if (snapshot)
    {
    vtkVVSnapshotPoolInternals::SnapshotPoolIterator it = 
      this->Internals->SnapshotPool.begin();
    vtkVVSnapshotPoolInternals::SnapshotPoolIterator end = 
      this->Internals->SnapshotPool.end();
    for (; it != end; ++it)
      {
      if ((*it) == snapshot)
        {
        return r;
        }
      ++r;
      }
    }
  return -1;
}

//----------------------------------------------------------------------------
void vtkVVSnapshotPool::RemoveAllSnapshots()
{
  if (this->Internals)
    {
    // Inefficient but there is too many things to do in RemoveSnapshot,
    // let's not duplicate and go out of sync

    while (this->Internals->SnapshotPool.size())
      {
      this->RemoveSnapshot(
        (*this->Internals->SnapshotPool.begin()));
      }
    }
}

//----------------------------------------------------------------------------
void vtkVVSnapshotPool::RemoveSnapshot(vtkVVSnapshot *snapshot)
{
  if (!snapshot)
    {
    return;
    }

  // Remove snapshot

  vtkObject *obj;

  vtkVVSnapshotPoolInternals::SnapshotPoolIterator it = 
    this->Internals->SnapshotPool.begin();
  vtkVVSnapshotPoolInternals::SnapshotPoolIterator end = 
    this->Internals->SnapshotPool.end();
  for (; it != end; ++it)
    {
    if ((*it) == snapshot)
      {
      obj = (vtkObject*)(*it);
      (*it)->UnRegister(this);

      this->Internals->SnapshotPool.erase(it);
      break;
      }
    }
}

//----------------------------------------------------------------------------
int vtkVVSnapshotPool::AddSnapshot(vtkVVSnapshot *snapshot)
{
  if (!snapshot)
    {
    vtkErrorMacro("can not add NULL snapshot to pool!");
    return 0;
    }

  // Already in the pool ?

  if (this->HasSnapshot(snapshot))
    {
    vtkErrorMacro("The snapshot is already in the pool!");
    return 0;
    }
  
  this->Internals->SnapshotPool.push_back(snapshot);
  snapshot->Register(this);

  return 1;
}

//----------------------------------------------------------------------------
void vtkVVSnapshotPool::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);

  os << indent << "Snapshots (" << this->GetNumberOfSnapshots() << "):\n";
  indent = indent.GetNextIndent();
  for (int i = 0; i < this->GetNumberOfSnapshots(); i++)
    {
    vtkVVSnapshot *snapshot = this->GetNthSnapshot(i);
    os << indent << "Snapshot #" << i << ": " << snapshot << endl;
    snapshot->PrintSelf(os, indent);
    }
}
