//=========================================================================
//  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 "vtkCMBArcCreateOperator.h"

#include "vtkCMBArc.h"
#include "vtkCMBArcEndNode.h"
#include "vtkCMBArcManager.h"

#include "vtkCellArray.h"
#include "vtkIdTypeArray.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkPolyData.h"
#include "vtkSmartPointer.h"

vtkStandardNewMacro(vtkCMBArcCreateOperator);

vtkCMBArcCreateOperator::vtkCMBArcCreateOperator()
{
  this->CreatedArcId = -1;
}

vtkCMBArcCreateOperator::~vtkCMBArcCreateOperator()
{
}

bool vtkCMBArcCreateOperator::Operate(vtkPolyData* source)
{
  if (source == NULL)
  {
    return false;
  }

  //we need at least two point to create a valid arc
  if (source->GetNumberOfPoints() < 2 || source->GetNumberOfLines() == 0)
  {
    return false;
  }
  //create the new arc we are going to add all the info too
  vtkCMBArc* createdArc = vtkCMBArc::New();
  createdArc->ClearPoints();

  this->CreatedArcId = createdArc->GetId();

  //variables for polydata to arc conversion
  double pos[3];
  vtkCellArray* lines = source->GetLines();
  vtkSmartPointer<vtkIdList> ids = vtkSmartPointer<vtkIdList>::New();

  vtkIdType currentIndex = 0;
  vtkIdType numberOfCells = lines->GetNumberOfCells();
  vtkIdType numberOfInternalEndNodes = lines->GetNumberOfConnectivityEntries() - numberOfCells;
  vtkDataArray* vda = source->GetPointData()->GetScalars();

  //walk the polydata and create the arc
  lines->InitTraversal();
  while (lines->GetNextCell(ids))
  {
    //for each cell we convert the ids from the old set, to the new id's
    for (vtkIdType i = 0; i < ids->GetNumberOfIds(); ++i)
    {
      source->GetPoint(ids->GetId(i), pos);
      unsigned int pointID = static_cast<unsigned int>(i);
      if (vda != NULL)
      {
        pointID = static_cast<unsigned int>(vda->GetTuple1(ids->GetId(i)));
      }
      vtkCMBArc::Point tmpPt(pos, pointID);
      if (currentIndex != 0 && currentIndex != numberOfInternalEndNodes - 1)
      {
        createdArc->InsertNextPoint(tmpPt);
      }
      else if (currentIndex == 0)
      {
        createdArc->SetEndNode(0, tmpPt);
      }
      else
      {
        createdArc->SetEndNode(1, tmpPt);
      }
      ++currentIndex;
    }
    //clear the id structures
    ids->Reset();
  }

  return true;
}

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