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

  Program:   Visualization Toolkit
  Module:    vtkPTSPropertyManager.h

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.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.

=========================================================================*/
/**
 * @class vtkPTSPropertyManager
 * @brief A microservice to set and get properties of a proxy
 *
 * vtkPTSPropertyManager allows to set and get properties of a proxy in a uniform way. It serves as
 * a base class for Python's PropertyManager.
 *
 */

#ifndef vtkPTSPropertyManager_h
#define vtkPTSPropertyManager_h
#include "vtkRemotingMicroservicesModule.h" // for exports

#include "vtkObject.h"
#include "vtkVariant.h"

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

#include "vtk_rxcpp.h" // for rxcpp
// clang-format off
// ideally, we include rx-lite.hpp here.
#include VTK_REMOTING_RXCPP(rx.hpp)
// clang-format on

class vtkSMProxy;

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

#ifndef __WRAP__
  std::vector<vtkVariant> GetPropertyValue(vtkSMProxy* proxy, const std::string& name);
  void SetPropertyValue(
    vtkSMProxy* proxy, const std::string& name, const std::vector<vtkVariant>& value);
  void SetPropertyValue(vtkSMProxy* proxy, const std::string& name, const vtkVariant& value);
#endif

  // FIXME ASYNC
  // Do we want changeSet getters/setters ?
  // void SetProperties(std::map<std::string, std::vector<vtkVariant>> changeSet)
  // std::map<std::string, std::vector<vtkVariant>> GetProperties()

  // Current python wrapping cannot handle std::vector<vtkVariant>. We use the *Element signatures
  // instead and re-implement Set/GetPropertyValue in Python class. For the *Element variations one
  // needs to call proxy->UpdateVTKObject() once all elements are set to push values to the remote
  // object.
  void SetPropertyValueElement(
    vtkSMProxy* proxy, const std::string& name, const vtkVariant& value, int index);
  vtkVariant GetPropertyValueElement(vtkSMProxy* proxy, const std::string& name, int index);

  int GetNumberOfValues(vtkSMProxy* proxy, const std::string& name);
  void SetNumberOfValues(vtkSMProxy* proxy, const std::string& name, int size);

protected:
  vtkPTSPropertyManager();
  ~vtkPTSPropertyManager() override;

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

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

#endif
