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

  Program: ParaView
  Module:  vtkPVDataDeliveryManager

  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.

=========================================================================*/
/**
 * @class vtkPVDataDeliveryManager
 * @brief manager for data-delivery.
 *
 * ParaView's multi-configuration / multi-process modes pose a challenge for
 * views. At runtime, the current configuration will determine which processes
 * have what parts of data and which processes are expected to "render" that data.
 * While views and their representations may add certain qualifiers to this
 * statement, generally speaking, all views have to support taking the data from
 * the data-processing nodes and delivering it to the rendering nodes. This is
 * where vtkPVDataDeliveryManager comes in play. It helps views (viz. vtkPVView
 * subclasses) move the data.
 */

#ifndef vtkPVDataDeliveryManager_h
#define vtkPVDataDeliveryManager_h

#include "vtkBoundingBox.h" // needed for vtkBoundingBox
#include "vtkNJson.h" // for vtkNJson
#include "vtkObject.h"
#include "vtkRemotingServerManagerViewsModule.h" //needed for exports
#include "vtkSmartPointer.h"                     // needed for iVar.
#include "vtkTuple.h"                            // needed for vtkTuple.

#include <map> // for std::map
#include <memory> // for std::unique_ptr

class vtkAlgorithmOutput;
class vtkDataObject;
class vtkExtentTranslator;
class vtkInformation;
class vtkInformationIntegerKey;
class vtkPVDataRepresentation;
class vtkPVView;

class VTKREMOTINGSERVERMANAGERVIEWS_EXPORT vtkPVDataDeliveryManager : public vtkObject
{
public:
  static vtkPVDataDeliveryManager* New();
  vtkTypeMacro(vtkPVDataDeliveryManager, vtkObject);
  void PrintSelf(ostream& os, vtkIndent indent) override;

  //@{
  /**
   * Get/Set the render-view. The view is not reference counted.
   */
  void SetView(vtkPVView*);
  vtkPVView* GetView() const;
  //@}

  ///@{
  /**
   * View uses these methods to register a representation with the storage. This
   * makes it possible for representations to communicate with the storage
   * directly using a self pointer, while enables views on different processes
   * to communicate information about representations using global ids.
   */
  void RegisterRepresentation(vtkPVDataRepresentation* repr);
  void UnRegisterRepresentation(vtkPVDataRepresentation*);
  ///@}

  ///@{
  /**
   * Representations (indirectly via vtkPVRenderView::SetPiece()) call this
   * method to register the geometry type they are rendering. Every
   * representation that requires delivering of any geometry must register with
   * the vtkPVDataDeliveryManager and never manage the delivery on its own.
   */
  void SetPiece(vtkPVDataRepresentation* repr, int port, vtkDataObject* data, bool useLOD);
  vtkSmartPointer<vtkDataObject> GetPiece(vtkPVDataRepresentation* repr, int port, bool useLOD);
  bool HasPiece(vtkPVDataRepresentation* repr, int port, bool useLOD);
  ///@}

  ///@{
  /**
   * Set/Get meta-data container for the specific piece. Views can use it to
   * store arbitrary metadata for each piece.
   */
  vtkInformation* GetInformation(vtkPVDataRepresentation* repr, int port, bool useLOD);
  ///@}

  /**
   * Returns the size for all visible geometries.
   */
  vtkTypeUInt64 GetVisibleDataSize(bool useLOD) const;

  ///@{
  /**
   * Get/Set data for rendering. Internal methods used by vtkRemoteObjectProviderViews.
   */
  std::map<std::string, vtkSmartPointer<vtkObject>> GetData(vtkMTimeType timestamp) const;
  void SetData(const std::map<std::string, vtkSmartPointer<vtkObject>>& data);
  ///@}

  /**
   * Releases all redistributed data.
   */
  void ReleaseRedistributedData();

  /**
   * Flags that control how data is to be handled when ordered compositing is
   * needed.
   */
  static vtkInformationIntegerKey* ORDERED_COMPOSITING_CONFIGURATION();

  void RedistributeDataForOrderedCompositing();

  ///@{
  /**
   * Provides access to the "cuts" built by this class when doing ordered
   * compositing. Note, this may not be up-to-date unless ordered compositing is
   * being used and are only available on the rendering-ranks i.e. pvserver or
   * pvrenderserver ranks.
   */
  const std::vector<vtkBoundingBox>& GetCuts() const;
  vtkTimeStamp GetCutsMTime() const;
  ///@}

  ///@{
  /**
   * When using an internally generated kd-tree for ordered compositing, this
   * method provides access to the complete kd-tree and the rendering rank
   * assignments for each node in the kd-tree.
   *
   * These are empty when the explicit data bounds are being used to determine
   * sorting order i.e. when vtkPVRenderViewDataDeliveryManager does not
   * generate its own kd tree internally instead relies on the representation
   * provided partitioning.
   */
  const std::vector<vtkBoundingBox>& GetRawCuts() const;
  const std::vector<int>& GetRawCutsRankAssignments() const;
  ///@}

protected:
  vtkPVDataDeliveryManager();
  ~vtkPVDataDeliveryManager() override;

private:
  vtkPVDataDeliveryManager(const vtkPVDataDeliveryManager&) = delete;
  void operator=(const vtkPVDataDeliveryManager&) = delete;

  class vtkInternals;
  std::unique_ptr<vtkInternals> Internals;
};

#endif
