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

  Program:   Visualization Toolkit
  Module:    vtkPTSPropertyManager.cxx

  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.

=========================================================================*/
#include "vtkPTSPropertyManager.h"
#include "vtkSMProperty.h"
#include "vtkSMPropertyHelper.h"
#include "vtkSMPropertyIterator.h"
#include "vtkSMProxy.h"
#include "vtkSMProxyListDomain.h"
#include "vtkVariant.h"

class vtkPTSPropertyManager::vtkInternals
{
public:
};

//-----------------------------------------------------------------------------
vtkStandardNewMacro(vtkPTSPropertyManager);
//-----------------------------------------------------------------------------
vtkPTSPropertyManager::vtkPTSPropertyManager()
  : Internals(new vtkPTSPropertyManager::vtkInternals())
{
}
//-----------------------------------------------------------------------------
vtkPTSPropertyManager::~vtkPTSPropertyManager() = default;
//-----------------------------------------------------------------------------
std::vector<vtkVariant> vtkPTSPropertyManager::GetPropertyValue(
  vtkSMProxy* proxy, const std::string& name)
{
  std::vector<vtkVariant> value;
  vtkSMProperty* property = proxy->GetProperty(name.c_str());
  if (!property)
  {
    vtkLogF(ERROR, "unknown property %s for proxy %s", name.c_str(), proxy->GetXMLName());
  }
  vtkSMPropertyHelper helper(property);
  value.resize(helper.GetNumberOfElements());
  for (int i = 0; i < helper.GetNumberOfElements(); i++)
  {
    value[i] = helper.GetAsVariant(i);
  }
  return value;
}

//-----------------------------------------------------------------------------
void vtkPTSPropertyManager::SetPropertyValue(
  vtkSMProxy* proxy, const std::string& name, const vtkVariant& value)
{
  const std::vector<vtkVariant> array({ value });
  this->SetPropertyValue(proxy, name, array);
}

//-----------------------------------------------------------------------------
void vtkPTSPropertyManager::SetPropertyValue(
  vtkSMProxy* proxy, const std::string& name, const std::vector<vtkVariant>& value)
{
  vtkSMProperty* property = proxy->GetProperty(name.c_str());
  if (!property)
  {
    vtkLogF(ERROR, "unknown property %s for proxy %s", name.c_str(), proxy->GetXMLName());
  }
  vtkSMPropertyHelper helper(property);
  if (helper.GetNumberOfElements() != value.size())
  {
    vtkLogF(ERROR, "Size mitsmatch between property %s and vector size: %ld !", name.c_str(),
      value.size());
    return;
  }
  for (unsigned int i = 0; i < helper.GetNumberOfElements(); i++)
  {
    if (helper.GetAsVariant(i) != value[i])
    {
      helper.Set(i, value[i]);
    }
  }
  proxy->UpdateVTKObjects();
}

//-----------------------------------------------------------------------------
void vtkPTSPropertyManager::SetPropertyValueElement(
  vtkSMProxy* proxy, const std::string& name, const vtkVariant& value, int index)
{
  vtkSMProperty* property = proxy->GetProperty(name.c_str());
  if (!property)
  {
    vtkLogF(ERROR, "unknown property %s for proxy %s", name.c_str(), proxy->GetXMLName());
  }
  vtkSMPropertyHelper helper(property);
  if (helper.GetNumberOfElements() <= index)
  {
    vtkLogF(ERROR, "Size mitsmatch between property %s and index: %d !", name.c_str(), index);
    return;
  }

  vtkVariant transformedValue = value;

  // string was passed for a proxy property. Check if there is an arraylist
  // domain and convert the value to a proxy
  if (value.IsString() && property->GetElementType() == vtkSMPropertyTypes::PROXY)
  {
    if (vtkSMProxyListDomain* domain = property->FindDomain<vtkSMProxyListDomain>())
    {
      vtkSMProxy* pvalue = domain->GetProxyWithName(value.ToString());
      transformedValue = pvalue;
    }
    else
    {
      vtkLogF(ERROR, "Type mitsmatch between property %s and value of type: %d !", name.c_str(),
        value.GetType());
      return;
    }
  }

  helper.Set(index, transformedValue);
}

//-----------------------------------------------------------------------------
vtkVariant vtkPTSPropertyManager::GetPropertyValueElement(
  vtkSMProxy* proxy, const std::string& name, int index)
{
  vtkSMProperty* property = proxy->GetProperty(name.c_str());
  if (!property)
  {
    vtkLogF(ERROR, "unknown property %s for proxy %s", name.c_str(), proxy->GetXMLName());
  }
  vtkSMPropertyHelper helper(property);
  vtkVariant value = helper.GetAsVariant(index);
  return value;
}

//-----------------------------------------------------------------------------
int vtkPTSPropertyManager::GetNumberOfValues(vtkSMProxy* proxy, const std::string& name)
{
  vtkSMProperty* property = proxy->GetProperty(name.c_str());
  if (!property)
  {
    vtkLogF(ERROR, "unknown property %s for proxy %s", name.c_str(), proxy->GetXMLName());
    return -1;
  }
  vtkSMPropertyHelper helper(property);
  return helper.GetNumberOfElements();
}

//-----------------------------------------------------------------------------
void vtkPTSPropertyManager::SetNumberOfValues(vtkSMProxy* proxy, const std::string& name, int size)
{
  vtkSMProperty* property = proxy->GetProperty(name.c_str());
  if (!property)
  {
    vtkLogF(ERROR, "unknown property %s for proxy %s", name.c_str(), proxy->GetXMLName());
    return;
  }
  vtkSMPropertyHelper helper(property);
  helper.SetNumberOfElements(size);
}

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