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

  Program:   ParaView
  Module:    vtkSMPlotMatrixViewProxy.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 "vtkSMPlotMatrixViewProxy.h"
#include "vtkScatterPlotMatrix.h"

#include "vtkClientServerStream.h"
#include "vtkDoubleArray.h"
#include "vtkIdTypeArray.h"
#include "vtkObjectFactory.h"
#include "vtkPVPlotMatrixView.h"
#include "vtkPVXMLElement.h"
#include "vtkCommand.h"
#include "vtkVector.h"

#include "vtkSMSession.h"

vtkStandardNewMacro(vtkSMPlotMatrixViewProxy);

//---------------------------------------------------------------------------
vtkSMPlotMatrixViewProxy::vtkSMPlotMatrixViewProxy()
{
  this->ActiveChanged = false;
}

//---------------------------------------------------------------------------
vtkSMPlotMatrixViewProxy::~vtkSMPlotMatrixViewProxy()
{
  this->SetVTKClassName(0);
}

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

//----------------------------------------------------------------------------
void vtkSMPlotMatrixViewProxy::CreateVTKObjects()
{
  if (this->ObjectsCreated)
    return;
  this->Superclass::CreateVTKObjects();

  vtkPVPlotMatrixView *matrix =
      vtkPVPlotMatrixView::SafeDownCast(this->GetClientSideObject());
  if (matrix)
    {
//    matrix->AddObserver(vtkCommand::AnnotationChangedEvent, this,
//                        &vtkSMPlotMatrixViewProxy::ActivePlotChanged);
    matrix->AddObserver(vtkCommand::CreateTimerEvent, this,
                        &vtkSMPlotMatrixViewProxy::SendAnimationPath);
    matrix->AddObserver(vtkCommand::AnimationCueTickEvent, this,
                        &vtkSMPlotMatrixViewProxy::AnimationTickEvent);
    }
}

//----------------------------------------------------------------------------
void vtkSMPlotMatrixViewProxy::ActivePlotChanged()
{
  this->ActiveChanged = true;
}

//----------------------------------------------------------------------------
void vtkSMPlotMatrixViewProxy::PostRender(bool interactive)
{
  this->Superclass::PostRender(interactive);

  if (this->ActiveChanged)
    {
    vtkPVPlotMatrixView *matrix =
        vtkPVPlotMatrixView::SafeDownCast(this->GetClientSideObject());
    if (matrix)
      {
      vtkClientServerStream stream;
      stream << vtkClientServerStream::Invoke
             << VTKOBJECT(this) << "SetActivePlot"
             << matrix->GetActiveRow() << matrix->GetActiveColumn()
             << vtkClientServerStream::End;
      this->ExecuteStream(stream);
      this->ActiveChanged = false;
      }
    }
}

//----------------------------------------------------------------------------
void vtkSMPlotMatrixViewProxy::AnimationTickEvent()
{
  if (this->Session->GetProcessRoles() != vtkPVSession::CLIENT_AND_SERVERS)
    {
    vtkClientServerStream stream;
    stream << vtkClientServerStream::Invoke
           << VTKOBJECT(this) << "AdvanceAnimationPath"
           << vtkClientServerStream::End;
    this->ExecuteStream(stream, false, vtkPVSession::RENDER_SERVER);
    }
}

//----------------------------------------------------------------------------
void vtkSMPlotMatrixViewProxy::SendAnimationPath()
{
  // Only send this to the render server(s) if we are not in builtin mode.
  if (this->Session->GetProcessRoles() != vtkPVSession::CLIENT_AND_SERVERS)
    {
    vtkPVPlotMatrixView *matrix =
        vtkPVPlotMatrixView::SafeDownCast(this->GetClientSideObject());
    if (!matrix)
      {
      return;
      }
    vtkScatterPlotMatrix *plotMatrix =
        vtkScatterPlotMatrix::SafeDownCast(matrix->GetContextItem());
    if (!plotMatrix || plotMatrix->GetNumberOfAnimationPathElements() == 0)
      {
      return;
      }

    vtkIdType n = plotMatrix->GetNumberOfAnimationPathElements();

    vtkClientServerStream stream;
    stream << vtkClientServerStream::Invoke
           << VTKOBJECT(this) << "ClearAnimationPath"
           << vtkClientServerStream::End;

    for (vtkIdType i = 0; i < n; ++i)
      {
      vtkVector2i element = plotMatrix->GetAnimationPathElement(i);
      stream << vtkClientServerStream::Invoke
             << VTKOBJECT(this) << "AddAnimationPath"
             << element[0] << element[1]
             << vtkClientServerStream::End;
      }

    stream << vtkClientServerStream::Invoke
           << VTKOBJECT(this) << "StartAnimationPath"
           << vtkClientServerStream::End;

    this->ExecuteStream(stream, false, vtkPVSession::RENDER_SERVER);
    this->MarkModified(this);
    }
}



//----------------------------------------------------------------------------
vtkAbstractContextItem* vtkSMPlotMatrixViewProxy::GetContextItem()
{
  vtkPVPlotMatrixView* pvview = vtkPVPlotMatrixView::SafeDownCast(
    this->GetClientSideObject());
  return pvview? pvview->GetContextItem() : NULL;
}
