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

  Program:   ParaView
  Module:    vtkPVServerInformation.cxx

  Copyright (c) Kitware, Inc.
  All rights reserved.
  See Copyright.txt or http://www.paraview.org/HTML/Copyright.html 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 "vtkPVServerInformation.h"

#include "vtkClientServerStream.h"
#include "vtkMultiProcessController.h"
#include "vtkObjectFactory.h"
#include "vtkProcessModule.h"
#include "vtkPVConfig.h"
#include "vtkPVServerOptions.h"
#include "vtkPVServerOptionsInternals.h"
#include "vtkPVConfig.h"
#include "vtkPVSession.h"
#include "vtkCompositeMultiProcessController.h"

// ------------------------
// NOTE for OGVSupport
// ------------------------
// Ideally, we should include vtkIOMovieConfigure to determine if OGGTHEORA
// support has been enabled. However, this module cannot depend on vtkIOMovie
// (for Catalyst builds). Also, since vtkOggTheoraWriter is used in
// vtkPVServerManagerDefault module which adds a hard dependency on vtkIOMovie
// module, that can indeed check is OGGTHEORA support is available. So it's
// reasonably safe to assume OGGTHEORA is always enabled here.
// #include "vtkIOMovieConfigure.h"

vtkStandardNewMacro(vtkPVServerInformation);

//----------------------------------------------------------------------------
vtkPVServerInformation::vtkPVServerInformation()
{
  this->MultiClientsEnable = 0;
  this->ClientId = 0;
  vtkMultiProcessController* controller =
    vtkMultiProcessController::GetGlobalController();
  this->NumberOfProcesses = controller ? controller->GetNumberOfProcesses():1;
  this->MPIInitialized =
    controller ? controller->IsA("vtkMPIController") != 0 : false;
  this->RootOnly = 1;
  this->RemoteRendering = 1;
  this->TileDimensions[0] = this->TileDimensions[1] = 0;
  this->TileMullions[0] = this->TileMullions[1] = 0;
  this->UseOffscreenRendering = 0;
  this->Timeout = 0;
#if defined(PARAVIEW_USE_ICE_T) && defined(PARAVIEW_USE_MPI)
  this->UseIceT = 1;
#else
  this->UseIceT = 0;
#endif

  this->AVISupport = 0;
#if defined(_WIN32)
  this->AVISupport = 1;
#else
# if defined(PARAVIEW_ENABLE_FFMPEG)
  this->AVISupport = 1;
# endif
#endif

  // Refer to note at the top of this file abount OGVSupport.
  this->OGVSupport = 1;

  this->MachinesInternals = new vtkPVServerOptionsInternals;
}

//----------------------------------------------------------------------------
vtkPVServerInformation::~vtkPVServerInformation()
{
  delete this->MachinesInternals;
}

//----------------------------------------------------------------------------
void vtkPVServerInformation::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
  os << indent << "RemoteRendering: " << this->RemoteRendering << endl;
  os << indent << "UseOffscreenRendering: " << this->UseOffscreenRendering << endl;
  os << indent << "TileDimensions: " << this->TileDimensions[0]
     << ", " << this->TileDimensions[1] << endl;
  os << indent << "TileMullions: " << this->TileMullions[0]
     << ", " << this->TileMullions[1] << endl;
  os << indent << "UseIceT: " << this->UseIceT << endl;
  os << indent << "OGVSupport: " << this->OGVSupport << endl;
  os << indent << "AVISupport: " << this->AVISupport << endl;
  os << indent << "Timeout: " << this->Timeout << endl;
  os << indent << "NumberOfProcesses: " << this->NumberOfProcesses << endl;
  os << indent << "MPIInitialized: " << this->MPIInitialized << endl;
  os << indent << "MultiClientsEnable: " << this->MultiClientsEnable << endl;
  os << indent << "ClientId: " << this->ClientId << endl;
}

//----------------------------------------------------------------------------
void vtkPVServerInformation::DeepCopy(vtkPVServerInformation *info)
{
  this->MultiClientsEnable = info->GetMultiClientsEnable();
  this->ClientId = info->GetClientId();
  this->RemoteRendering = info->GetRemoteRendering();
  info->GetTileDimensions(this->TileDimensions);
  info->GetTileMullions(this->TileMullions);
  this->UseOffscreenRendering = info->GetUseOffscreenRendering();
  this->UseIceT = info->GetUseIceT();
  this->Timeout = info->GetTimeout();
  this->SetNumberOfMachines(info->GetNumberOfMachines());
  unsigned int idx;
  for (idx = 0; idx < info->GetNumberOfMachines(); idx++)
    {
    this->SetEnvironment(idx, info->GetEnvironment(idx));
    this->SetGeometry(idx, info->GetGeometry(idx));
    this->SetFullScreen(idx, info->GetFullScreen(idx));
    this->SetShowBorders(idx, info->GetShowBorders(idx));
    this->SetStereoType(idx, info->GetStereoType(idx));
    this->SetLowerLeft(idx, info->GetLowerLeft(idx));
    this->SetLowerRight(idx, info->GetLowerRight(idx));
    this->SetUpperRight(idx, info->GetUpperRight(idx));
    }
  this->SetEyeSeparation(info->GetEyeSeparation());
  this->NumberOfProcesses = info->NumberOfProcesses;
  this->MPIInitialized = info->MPIInitialized;
}

//----------------------------------------------------------------------------
void vtkPVServerInformation::CopyFromObject(vtkObject* vtkNotUsed(obj))
{
  vtkProcessModule* pm = vtkProcessModule::GetProcessModule();
  if(!pm)
    {
    vtkWarningMacro("ProcessModule is not available.");
    return;
    }

  // Options
  vtkPVOptions* options = pm->GetOptions();
  options->GetTileDimensions(this->TileDimensions);
  options->GetTileMullions(this->TileMullions);
#if !defined(__APPLE__)
  this->UseOffscreenRendering = options->GetUseOffscreenRendering();
#else
  this->UseOffscreenRendering = 0;
#endif
  this->Timeout = options->GetTimeout();

  // Server options
  vtkPVServerOptions *serverOptions = vtkPVServerOptions::SafeDownCast(options);
  if (serverOptions)
    {
    this->MultiClientsEnable = serverOptions->GetMultiClientMode();
    this->SetNumberOfMachines(serverOptions->GetNumberOfMachines());
    unsigned int idx;
    for (idx = 0; idx < serverOptions->GetNumberOfMachines(); idx++)
      {
      this->SetEnvironment(idx, serverOptions->GetDisplayName(idx));
      this->SetGeometry(idx, serverOptions->GetGeometry(idx));
      this->SetFullScreen(idx, serverOptions->GetFullScreen(idx));
      this->SetShowBorders(idx, serverOptions->GetShowBorders(idx));
      this->SetStereoType(idx, serverOptions->GetStereoType(idx));
      this->SetLowerLeft(idx, serverOptions->GetLowerLeft(idx));
      this->SetLowerRight(idx, serverOptions->GetLowerRight(idx));
      this->SetUpperRight(idx, serverOptions->GetUpperRight(idx));
      }
    this->SetEyeSeparation(serverOptions->GetEyeSeparation());
    }

  vtkPVSession* session = vtkPVSession::SafeDownCast(pm->GetSession());
  vtkCompositeMultiProcessController* ctrl;
  if( session && (ctrl =
                  vtkCompositeMultiProcessController::SafeDownCast(session->GetController(vtkPVSession::CLIENT))))
    {
    this->ClientId = ctrl->GetActiveControllerID();
    }
  else
    {
    this->ClientId = 0;
    }
}

//----------------------------------------------------------------------------
// Consider an option added if it is a non-default option that the user
// has probably selected.
void vtkPVServerInformation::AddInformation(vtkPVInformation* info)
{
  vtkPVServerInformation* serverInfo;
  serverInfo = vtkPVServerInformation::SafeDownCast(info);
  if (serverInfo)
    {
    if (!serverInfo->GetRemoteRendering())
      {
      this->RemoteRendering = 0;
      }
    if (serverInfo->GetTileDimensions()[0])
      {
      serverInfo->GetTileDimensions(this->TileDimensions);
      }
    if (serverInfo->GetTileMullions()[0])
      {
      serverInfo->GetTileMullions(this->TileMullions);
      }
    if (serverInfo->GetUseOffscreenRendering())
      {
      this->UseOffscreenRendering = 1;
      }

    if (this->Timeout <= 0 ||
      (serverInfo->GetTimeout() > 0 && serverInfo->GetTimeout() < this->Timeout))
      {
      this->Timeout = serverInfo->GetTimeout();
      }

    if (!serverInfo->GetOGVSupport())
      {
      this->OGVSupport = 0;
      }

    if (!serverInfo->GetAVISupport())
      {
      this->AVISupport = 0;
      }

    // IceT either is there or is not.
    this->UseIceT = serverInfo->GetUseIceT();
    this->SetNumberOfMachines(serverInfo->GetNumberOfMachines());
    unsigned int idx;
    for (idx = 0; idx < serverInfo->GetNumberOfMachines(); idx++)
      {
      this->SetEnvironment(idx, serverInfo->GetEnvironment(idx));
      this->SetGeometry(idx, serverInfo->GetGeometry(idx));
      this->SetFullScreen(idx, serverInfo->GetFullScreen(idx));
      this->SetShowBorders(idx, serverInfo->GetShowBorders(idx));
      this->SetStereoType(idx, serverInfo->GetStereoType(idx));
      this->SetLowerLeft(idx, serverInfo->GetLowerLeft(idx));
      this->SetLowerRight(idx, serverInfo->GetLowerRight(idx));
      this->SetUpperRight(idx, serverInfo->GetUpperRight(idx));
      }
    this->SetEyeSeparation(serverInfo->GetEyeSeparation());

    if (this->NumberOfProcesses < serverInfo->NumberOfProcesses)
      {
      this->NumberOfProcesses = serverInfo->NumberOfProcesses;
      }
    this->MPIInitialized = serverInfo->MPIInitialized;
    if (this->MultiClientsEnable < serverInfo->MultiClientsEnable)
      {
      this->MultiClientsEnable = serverInfo->MultiClientsEnable;
      }
    if (this->ClientId < serverInfo->ClientId)
      {
      this->ClientId = serverInfo->ClientId;
      }
    }
}

//----------------------------------------------------------------------------
void vtkPVServerInformation::CopyToStream(vtkClientServerStream* css)
{
  css->Reset();
  *css << vtkClientServerStream::Reply;
  *css << this->RemoteRendering;
  *css << this->TileDimensions[0] << this->TileDimensions[1];
  *css << this->TileMullions[0] << this->TileMullions[1];
  *css << this->UseOffscreenRendering;
  *css << this->Timeout;
  *css << this->UseIceT;
  *css << "<obsolete>"; // we used to pass RenderModuleName.
  *css << this->OGVSupport;
  *css << this->AVISupport;
  *css << this->NumberOfProcesses;
  *css << this->MPIInitialized;
  *css << this->GetNumberOfMachines();
  unsigned int idx;
  for (idx = 0; idx < this->GetNumberOfMachines(); idx++)
    {
    *css << this->GetEnvironment(idx);
    *css << this->GetGeometry(idx)[0] << this->GetGeometry(idx)[1]
         << this->GetGeometry(idx)[2] << this->GetGeometry(idx)[3];
    *css << this->GetFullScreen(idx);
    *css << this->GetShowBorders(idx);
    *css << this->GetStereoType(idx);
    *css << this->GetLowerLeft(idx)[0] << this->GetLowerLeft(idx)[1]
         << this->GetLowerLeft(idx)[2];
    *css << this->GetLowerRight(idx)[0] << this->GetLowerRight(idx)[1]
         << this->GetLowerRight(idx)[2];
    *css << this->GetUpperRight(idx)[0] << this->GetUpperRight(idx)[1]
         << this->GetUpperRight(idx)[2];
    }
  *css << this->GetEyeSeparation();
  *css << this->MultiClientsEnable;
  *css << this->ClientId;
  *css << vtkClientServerStream::End;
}

//----------------------------------------------------------------------------
void vtkPVServerInformation::CopyFromStream(const vtkClientServerStream* css)
{
  if(!css->GetArgument(0, 0, &this->RemoteRendering))
    {
    vtkErrorMacro("Error parsing RemoteRendering from message.");
    return;
    }
  if(   !css->GetArgument(0, 1, &this->TileDimensions[0])
     || !css->GetArgument(0, 2, &this->TileDimensions[1]) )
    {
    vtkErrorMacro("Error parsing TileDimensions from message.");
    return;
    }
  if(   !css->GetArgument(0, 3, &this->TileMullions[0])
     || !css->GetArgument(0, 4, &this->TileMullions[1]) )
    {
    vtkErrorMacro("Error parsing TileMullions from message.");
    return;
    }
  if(!css->GetArgument(0, 5, &this->UseOffscreenRendering))
    {
    vtkErrorMacro("Error parsing UseOffscreenRendering from message.");
    return;
    }
  if(!css->GetArgument(0, 6, &this->Timeout))
    {
    vtkErrorMacro("Error parsing Timeout from message.");
    return;
    }
  if (!css->GetArgument(0, 7, &this->UseIceT))
    {
    vtkErrorMacro("Error parsing IceT flag from message.");
    return;
    }
  // for client-server compatibility,
  const char *rmName;
  if (!css->GetArgument(0, 8, &rmName))
    {
    vtkErrorMacro("Error parsing render module name from message.");
    return;
    }
  // leaving this for client-server compatibility.
  // this->SetRenderModuleName(rmName);
  if (!css->GetArgument(0, 9, &this->OGVSupport))
    {
    vtkErrorMacro("Error parsing OGVSupport flag from message.");
    return;
    }
  if (!css->GetArgument(0, 10, &this->AVISupport))
    {
    vtkErrorMacro("Error parsing AVISupport flag from message.");
    return;
    }
  int numProcs;
  if (!css->GetArgument(0, 11, &numProcs))
    {
    vtkErrorMacro("Error parsing number of processes from message.");
    return;
    }
  this->NumberOfProcesses = numProcs;

  bool mpiInitialized;
  if (!css->GetArgument(0, 12, &mpiInitialized))
    {
    vtkErrorMacro("Error parsing mpi initialized from message.");
    return;
    }
  this->MPIInitialized = mpiInitialized;

  unsigned int numMachines;
  if (!css->GetArgument(0, 13, &numMachines))
    {
    vtkErrorMacro("Error parsing number of machines from message.");
    return;
    }
  this->SetNumberOfMachines(numMachines);
  unsigned int idx;
  const char* env;
  int machineOffset = 14;
  int valuesPerMachine = 17;
  for (idx = 0; idx < numMachines; idx++)
    {
    int machineIndex = machineOffset + idx * valuesPerMachine;
    int currentValueOffset = 0;
    if (!css->GetArgument(0, machineIndex + currentValueOffset++, &env))
      {
      vtkErrorMacro("Error parsing display environment from message for "<< idx);
      return;
      }
    this->MachinesInternals->MachineInformationVector[idx].Environment = env;
    if (!css->GetArgument(0, machineIndex + currentValueOffset++,
                          &this->MachinesInternals->MachineInformationVector[idx].Geometry[0]) ||
        !css->GetArgument(0, machineIndex + currentValueOffset++,
                          &this->MachinesInternals->MachineInformationVector[idx].Geometry[1]) ||
        !css->GetArgument(0, machineIndex + currentValueOffset++,
                          &this->MachinesInternals->MachineInformationVector[idx].Geometry[2]) ||
        !css->GetArgument(0, machineIndex + currentValueOffset++,
                          &this->MachinesInternals->MachineInformationVector[idx].Geometry[3]))
      {
      vtkErrorMacro("Error parsing window geometry from message.");
      return;
      }
    if (!css->GetArgument(0, machineIndex + currentValueOffset++,
                          &this->MachinesInternals->MachineInformationVector[idx].FullScreen))
      {
      vtkErrorMacro("Error parsing FullScreen flag from message.");
      return;
      }
    if (!css->GetArgument(0, machineIndex + currentValueOffset++,
                          &this->MachinesInternals->MachineInformationVector[idx].ShowBorders))
      {
      vtkErrorMacro("Error parsing ShowBorders flag from message.");
      return;
      }
    if (!css->GetArgument(0, machineIndex + currentValueOffset++,
                          &this->MachinesInternals->MachineInformationVector[idx].StereoType))
      {
      vtkErrorMacro("Error parsing StereoType flag from message.");
      return;
      }
    if (!css->GetArgument(0, machineIndex + currentValueOffset++,
                          &this->MachinesInternals->MachineInformationVector[idx].LowerLeft[0]) ||
        !css->GetArgument(0, machineIndex + currentValueOffset++,
                          &this->MachinesInternals->MachineInformationVector[idx].LowerLeft[1]) ||
        !css->GetArgument(0, machineIndex + currentValueOffset++,
                          &this->MachinesInternals->MachineInformationVector[idx].LowerLeft[2]))
      {
      vtkErrorMacro("Error parsing lower left coordinate from message.");
      return;
      }
    if (!css->GetArgument(0, machineIndex + currentValueOffset++,
                          &this->MachinesInternals->MachineInformationVector[idx].LowerRight[0]) ||
        !css->GetArgument(0, machineIndex + currentValueOffset++,
                          &this->MachinesInternals->MachineInformationVector[idx].LowerRight[1]) ||
        !css->GetArgument(0, machineIndex + currentValueOffset++,
                          &this->MachinesInternals->MachineInformationVector[idx].LowerRight[2]))
      {
      vtkErrorMacro("Error parsing lower right coordinate from message.");
      return;
      }
    if (!css->GetArgument(0, machineIndex + currentValueOffset++,
                          &this->MachinesInternals->MachineInformationVector[idx].UpperRight[0]) ||
        !css->GetArgument(0, machineIndex + currentValueOffset++,
                          &this->MachinesInternals->MachineInformationVector[idx].UpperRight[1]) ||
        !css->GetArgument(0, machineIndex + currentValueOffset++,
                          &this->MachinesInternals->MachineInformationVector[idx].UpperRight[2]))
      {
      vtkErrorMacro("Error parsing upper left coordinate from message.");
      return;
      }
    }
  double eyeSeparation;
  int epilogueOffset = machineOffset + numMachines * valuesPerMachine;
  if (!css->GetArgument(0, epilogueOffset, &eyeSeparation))
    {
    vtkErrorMacro("Error parsing eye-separations from message.");
    return;
    }
  this->SetEyeSeparation(eyeSeparation);

  if(!css->GetArgument(0, epilogueOffset + 1, &this->MultiClientsEnable))
    {
    vtkErrorMacro("Error parsing MultiClientsEnable from message.");
    return;
    }
  if(!css->GetArgument(0, epilogueOffset + 2, &this->ClientId))
    {
    vtkErrorMacro("Error parsing ClientId from message.");
    return;
    }
}

//----------------------------------------------------------------------------
void vtkPVServerInformation::SetEyeSeparation(double value)
{
  this->MachinesInternals->EyeSeparation = value;
}

//----------------------------------------------------------------------------
double vtkPVServerInformation::GetEyeSeparation() const
{
  return static_cast<double>(this->MachinesInternals->EyeSeparation);
}

//----------------------------------------------------------------------------
void vtkPVServerInformation::SetNumberOfMachines(unsigned int num)
{
  delete this->MachinesInternals;
  this->MachinesInternals = new vtkPVServerOptionsInternals;
  unsigned int idx;
  vtkPVServerOptionsInternals::MachineInformation info;
  for (idx = 0; idx < num; idx++)
    {
    this->MachinesInternals->MachineInformationVector.push_back(info);
    }
}

//----------------------------------------------------------------------------
unsigned int vtkPVServerInformation::GetNumberOfMachines() const
{
  return static_cast<unsigned int>(
    this->MachinesInternals->MachineInformationVector.size());
}

//----------------------------------------------------------------------------
void vtkPVServerInformation::SetEnvironment(unsigned int idx,
                                            const char* name)
{
  if (idx >= this->GetNumberOfMachines())
    {
    unsigned int i;
    vtkPVServerOptionsInternals::MachineInformation info;
    for (i = this->GetNumberOfMachines(); i <= idx; i++)
      {
      this->MachinesInternals->MachineInformationVector.push_back(info);
      }
    }

  this->MachinesInternals->MachineInformationVector[idx].Environment = name;
}

//----------------------------------------------------------------------------
const char* vtkPVServerInformation::GetEnvironment(unsigned int idx) const
{
  if (idx >= this->GetNumberOfMachines())
    {
    return NULL;
    }
  return this->MachinesInternals->MachineInformationVector[idx].Environment.c_str();
}

//----------------------------------------------------------------------------
void vtkPVServerInformation::SetGeometry(unsigned int idx, int geo[])
{
  if (idx >= this->GetNumberOfMachines())
    {
    unsigned int i;
    vtkPVServerOptionsInternals::MachineInformation info;
    for (i = this->GetNumberOfMachines(); i <= idx; i++)
      {
      this->MachinesInternals->MachineInformationVector.push_back(info);
      }
    }

  for (int i = 0; i < 4; ++i)
    {
    this->MachinesInternals->MachineInformationVector[idx].Geometry[i] = geo[i];
    }
}

//----------------------------------------------------------------------------
int* vtkPVServerInformation::GetGeometry(unsigned int idx) const
{
  if (idx >= this->GetNumberOfMachines())
    {
    return NULL;
    }
  return this->MachinesInternals->MachineInformationVector[idx].Geometry;
}

//----------------------------------------------------------------------------
void vtkPVServerInformation::SetFullScreen(unsigned int idx, bool fullscreen)
{
  if (idx >= this->GetNumberOfMachines())
    {
    unsigned int i;
    vtkPVServerOptionsInternals::MachineInformation info;
    for (i = this->GetNumberOfMachines(); i <= idx; i++)
      {
      this->MachinesInternals->MachineInformationVector.push_back(info);
      }
    }

  this->MachinesInternals->MachineInformationVector[idx].FullScreen = fullscreen;
}

//----------------------------------------------------------------------------
bool vtkPVServerInformation::GetFullScreen(unsigned int idx) const
{
  if (idx >= this->GetNumberOfMachines())
    {
    return false;
    }

  return this->MachinesInternals->MachineInformationVector[idx].FullScreen;
}

//----------------------------------------------------------------------------
void vtkPVServerInformation::SetShowBorders(unsigned int idx, bool borders)
{
  if (idx >= this->GetNumberOfMachines())
    {
    unsigned int i;
    vtkPVServerOptionsInternals::MachineInformation info;
    for (i = this->GetNumberOfMachines(); i <= idx; i++)
      {
      this->MachinesInternals->MachineInformationVector.push_back(info);
      }
    }

  this->MachinesInternals->MachineInformationVector[idx].ShowBorders = borders;
}

//----------------------------------------------------------------------------
bool vtkPVServerInformation::GetShowBorders(unsigned int idx) const
{
  if (idx >= this->GetNumberOfMachines())
    {
    return false;
    }

  return this->MachinesInternals->MachineInformationVector[idx].ShowBorders;
}

//----------------------------------------------------------------------------
void vtkPVServerInformation::SetStereoType(unsigned int idx, int type)
{
  if (idx >= this->GetNumberOfMachines())
    {
    unsigned int i;
    vtkPVServerOptionsInternals::MachineInformation info;
    for (i = this->GetNumberOfMachines(); i <= idx; i++)
      {
      this->MachinesInternals->MachineInformationVector.push_back(info);
      }
    }

  this->MachinesInternals->MachineInformationVector[idx].StereoType = type;
}

//----------------------------------------------------------------------------
int vtkPVServerInformation::GetStereoType(unsigned int idx) const
{
  if (idx >= this->GetNumberOfMachines())
    {
    return -1;
    }

  return this->MachinesInternals->MachineInformationVector[idx].StereoType;
}

//----------------------------------------------------------------------------
void vtkPVServerInformation::SetLowerLeft(unsigned int idx, double coord[3])
{
  if (idx >= this->GetNumberOfMachines())
    {
    unsigned int i;
    vtkPVServerOptionsInternals::MachineInformation info;
    for (i = this->GetNumberOfMachines(); i <= idx; i++)
      {
      this->MachinesInternals->MachineInformationVector.push_back(info);
      }
    }

  this->MachinesInternals->MachineInformationVector[idx].LowerLeft[0] = coord[0];
  this->MachinesInternals->MachineInformationVector[idx].LowerLeft[1] = coord[1];
  this->MachinesInternals->MachineInformationVector[idx].LowerLeft[2] = coord[2];
}

//----------------------------------------------------------------------------
double* vtkPVServerInformation::GetLowerLeft(unsigned int idx) const
{
  if (idx >= this->GetNumberOfMachines())
    {
    return NULL;
    }
  return this->MachinesInternals->MachineInformationVector[idx].LowerLeft;
}

//----------------------------------------------------------------------------
void vtkPVServerInformation::SetLowerRight(unsigned int idx, double coord[3])
{
  if (idx >= this->GetNumberOfMachines())
    {
    unsigned int i;
    vtkPVServerOptionsInternals::MachineInformation info;
    for (i = this->GetNumberOfMachines(); i <= idx; i++)
      {
      this->MachinesInternals->MachineInformationVector.push_back(info);
      }
    }

  this->MachinesInternals->MachineInformationVector[idx].LowerRight[0] = coord[0];
  this->MachinesInternals->MachineInformationVector[idx].LowerRight[1] = coord[1];
  this->MachinesInternals->MachineInformationVector[idx].LowerRight[2] = coord[2];
}

//----------------------------------------------------------------------------
double* vtkPVServerInformation::GetLowerRight(unsigned int idx) const
{
  if (idx >= this->GetNumberOfMachines())
    {
    return NULL;
    }
  return this->MachinesInternals->MachineInformationVector[idx].LowerRight;
}

//----------------------------------------------------------------------------
void vtkPVServerInformation::SetUpperRight(unsigned int idx, double coord[3])
{
  if (idx >= this->GetNumberOfMachines())
    {
    unsigned int i;
    vtkPVServerOptionsInternals::MachineInformation info;
    for (i = this->GetNumberOfMachines(); i <= idx; i++)
      {
      this->MachinesInternals->MachineInformationVector.push_back(info);
      }
    }

  this->MachinesInternals->MachineInformationVector[idx].UpperRight[0] = coord[0];
  this->MachinesInternals->MachineInformationVector[idx].UpperRight[1] = coord[1];
  this->MachinesInternals->MachineInformationVector[idx].UpperRight[2] = coord[2];
}

//----------------------------------------------------------------------------
double* vtkPVServerInformation::GetUpperRight(unsigned int idx) const
{
  if (idx >= this->GetNumberOfMachines())
    {
    return NULL;
    }
  return this->MachinesInternals->MachineInformationVector[idx].UpperRight;
}

//----------------------------------------------------------------------------
bool vtkPVServerInformation::IsMPIInitialized() const
{
  return this->MPIInitialized;
}
