//=========================================================================
//  Copyright (c) Kitware, Inc.
//  All rights reserved.
//  See LICENSE.txt 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 "pqCMBColorMapWidget.h"

#include "pqApplicationCore.h"
#include "pqDataRepresentation.h"
#include "pqProxyWidget.h"
#include "vtkCommand.h"
#include "vtkSMPVRepresentationProxy.h"
#include "vtkSMProperty.h"
#include "vtkSMPropertyHelper.h"
#include "vtkSMTransferFunctionProxy.h"
#include "vtkWeakPointer.h"

#include <QPointer>
#include <QVBoxLayout>

class pqCMBColorMapWidget::pqInternals
{
public:
  QPointer<pqProxyWidget> ProxyWidget;
  QPointer<pqDataRepresentation> ActiveRepresentation;
  unsigned long ObserverId;

  pqInternals(pqCMBColorMapWidget* vtkNotUsed(self))
    : ObserverId(0)
  {
  }

  ~pqInternals() {}
};

pqCMBColorMapWidget::pqCMBColorMapWidget(QWidget* parentObject)
  : Superclass(parentObject)
  , Internals(new pqCMBColorMapWidget::pqInternals(this))
{
  //  pqActiveObjects *activeObjects = &pqActiveObjects::instance();
  //  this->connect(activeObjects, SIGNAL(representationChanged(pqDataRepresentation*)),
  //    this, SLOT(updateActive()));
  new QVBoxLayout(this);
  this->layout()->setMargin(0);
  this->updateRepresentation();
}

pqCMBColorMapWidget::~pqCMBColorMapWidget()
{
  delete this->Internals;
  this->Internals = NULL;
}

void pqCMBColorMapWidget::updatePanel()
{
  if (this->Internals->ProxyWidget)
  {
    this->Internals->ProxyWidget->filterWidgets(true);
  }
}

void pqCMBColorMapWidget::updateRepresentation()
{
  //  pqDataRepresentation* repr =
  //    pqActiveObjects::instance().activeRepresentation();

  pqDataRepresentation* repr = this->Internals->ActiveRepresentation;
  // Set the current LUT proxy to edit.
  if (repr && vtkSMPVRepresentationProxy::GetUsingScalarColoring(repr->getProxy()))
  {
    this->setColorTransferFunction(
      vtkSMPropertyHelper(repr->getProxy(), "LookupTable", true).GetAsProxy());
  }
  else
  {
    this->setColorTransferFunction(NULL);
  }
}

void pqCMBColorMapWidget::setDataRepresentation(pqDataRepresentation* repr)
{
  // this method sets up hooks to ensure that when the repr's properties are
  // modified, the editor shows the correct LUT.
  if (this->Internals->ActiveRepresentation == repr)
  {
    return;
  }

  if (this->Internals->ActiveRepresentation)
  {
    // disconnect signals.
    if (this->Internals->ObserverId)
    {
      this->Internals->ActiveRepresentation->getProxy()->RemoveObserver(
        this->Internals->ObserverId);
    }
  }

  this->Internals->ObserverId = 0;
  this->Internals->ActiveRepresentation = repr;
  if (repr && repr->getProxy())
  {
    this->Internals->ObserverId = repr->getProxy()->AddObserver(
      vtkCommand::PropertyModifiedEvent, this, &pqCMBColorMapWidget::updateRepresentation);
  }
  this->updateRepresentation();
}

void pqCMBColorMapWidget::setColorTransferFunction(vtkSMProxy* ctf)
{
  if (this->Internals->ProxyWidget == NULL && ctf == NULL)
  {
    return;
  }
  if (this->Internals->ProxyWidget && ctf && this->Internals->ProxyWidget->proxy() == ctf)
  {
    return;
  }

  if ((ctf == NULL && this->Internals->ProxyWidget) ||
    (this->Internals->ProxyWidget && ctf && this->Internals->ProxyWidget->proxy() != ctf))
  {
    this->layout()->removeWidget(this->Internals->ProxyWidget);
    delete this->Internals->ProxyWidget;
  }

  if (!ctf)
  {
    return;
  }

  pqProxyWidget* widget = new pqProxyWidget(ctf, this);
  widget->setObjectName("Properties");
  widget->setApplyChangesImmediately(true);
  widget->filterWidgets();

  this->layout()->addWidget(widget);

  this->Internals->ProxyWidget = widget;
  this->updatePanel();

  QObject::connect(widget, SIGNAL(changeFinished()), this, SLOT(renderViews()));
}

void pqCMBColorMapWidget::renderViews()
{
  if (this->Internals->ActiveRepresentation)
  {
    this->Internals->ActiveRepresentation->renderViewEventually();
  }
}
