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

  Copyright (c) Kitware, Inc.
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/VolViewCopyright.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.

=========================================================================*/
// .NAME vtkKW3DMarkersWidget - widget for measuring distance along a line
// .SECTION Description

#ifndef __vtkKW3DMarkersWidget_h
#define __vtkKW3DMarkersWidget_h

#include "vtkKW3DWidget.h"
#include "XML/vtkXMLIOBaseMacros.h" // Needed for XML reader/writer macros

#include <vtkstd/vector> // used for keeping track of the Markers
#include <vtkstd/string> // used for keeping names and descriptions of Markers groups.

class vtkMarkerWidgetCallback;
class vtkActor;
class vtkCylinderSource;
class vtkPolyDataMapper;
class vtkProperty;
class vtkCellPicker;

class VTK_EXPORT vtkKW3DMarkersWidget : public vtkKW3DWidget
{
public:
  static vtkKW3DMarkersWidget *New();
  vtkTypeRevisionMacro(vtkKW3DMarkersWidget, vtkKW3DWidget);
  void PrintSelf(ostream& os, vtkIndent indent);
  //BTX
  vtkKWGetXMLReaderWriterObjectsMacro();
  //ETX

  void Update3DMarkers();
  
  virtual void SetEnabled(int enabling);

  // Description:
  // Add, query or remove a marker to a group.
  // Each marker has a unique ID (returned by AddMarker() for example). 
  // Each marker is assigned to one group ID.
  // Two markers can have the same position if they are in different groups.
  // GetMarkerIndex return -1 if no marker was found at that position/radius.
  // RemoveMarker return 1 if the marker was successfully removed, 0 otherwise.
  // RemoveAllMarkers return the number of markers removed.
  // RemoveAllMarkersInGroup return the number of markers removed.
  virtual int AddMarker(
    unsigned int gid, double x, double y, double z);
  virtual int  HasMarker(unsigned int gid, double x, double y, double z);
  virtual int  GetMarkerId(unsigned int gid, double x, double y, double z);
  virtual int GetMarkerGroupId(unsigned int id) const;
  virtual void SetMarkerPosition(
    unsigned int id, double x, double y, double z);
  virtual double* GetMarkerPosition(unsigned int id);
  virtual int RemoveMarker(unsigned int id);
  virtual int RemoveAllMarkers();
  virtual int RemoveAllMarkersInGroup(unsigned int gid);
 
  // Description:
  // Add, remove a group of markers. 
  // Each group has a unique ID (returned by AddMarkersGroup() for example). 
  // RemoveMarkersGroup return 1 if the marker was successfully removed, 
  // 0 otherwise.
  // RemoveAllMarkersGroups return the number of groups removed.
  virtual int AddMarkersGroup(const char *, const double * color);
  virtual int HasMarkersGroup(const char *);
  virtual int RemoveMarkersGroup(const char *);
  virtual int RemoveMarkersGroup(unsigned int gid);
  virtual int RemoveAllMarkersGroups();

  // Description:
  // Adjust properties of a markers group
  virtual void SetMarkersGroupColor(
    unsigned int gid, double r, double g, double b);
  virtual void SetMarkersGroupColor(unsigned int gid, const double rgb[3]) 
    { this->SetMarkersGroupColor(gid, rgb[0], rgb[1], rgb[2]); };
  virtual const char * GetMarkersGroupName(unsigned int gid) const;
  virtual int GetMarkersGroupId(const char *) const;
  virtual double* GetMarkersGroupColor(unsigned int gid) const;
  virtual unsigned int GetNumberOfMarkersGroups() const;
  virtual unsigned int GetDefaultMarkersGroupId() const;
  
  // Description:
  // Get the number and (x, y, z) position of the markers, the array for the 
  // positions must be passed in and be large enough. 
  virtual unsigned int GetNumberOfMarkers();

  // Description:
  // Used internally to set the selected marker 
  // GetSelectedMarkerIndex() return -1 if no selection.
  // RemoveSelectedMarker return 1 if the selected marker was successfully 
  // removed, 0 otherwise.
  virtual void SetSelectedMarker(vtkActor *);
  vtkGetMacro(SelectedMarkerIndex, int);
  virtual int RemoveSelectedMarker();

  // Description:
  // ProcessEvents dispatches to these methods.
  void OnLeftButtonDown();
  void OnLeftButtonUp();
  void OnMouseMove();
  void OnStartRender();

protected:
  vtkKW3DMarkersWidget();
  ~vtkKW3DMarkersWidget();

//BTX - manage the state of the widget
  int State;
  enum WidgetState
  {
    Start=0,
    Moving,
    Outside
  };
//ETX
  
  vtkCylinderSource *CylinderSource;
  vtkPolyDataMapper *CylinderMapper;
  
  // Do the picking
  vtkCellPicker *Picker;

  vtkActor *SelectedMarker;
  int SelectedMarkerIndex;
  vtkMarkerWidgetCallback *MarkerWidgetCallback;
  vtkMarkerWidgetCallback *MarkerWidgetRenderCallback;
  
//BTX
  typedef vtkstd::vector<vtkActor *> MarkersContainer;
  MarkersContainer Markers;
  
  typedef vtkstd::vector< unsigned int > MarkersGroupIdsContainer;
  MarkersGroupIdsContainer MarkersGroupIds;
  
  typedef vtkstd::string MarkersGroupNameType;
  typedef vtkstd::vector< MarkersGroupNameType > MarkersGroupNameContainer;
  MarkersGroupNameContainer MarkersGroupNames;
  
  typedef vtkstd::vector< vtkProperty  * > MarkersGroupPropertyContainer;
  MarkersGroupPropertyContainer  MarkersGroupProperty;

  MarkersGroupNameType DefaultGroupName;
//ETX

  int DeallocateMarkerResources(unsigned int id);

  // handles the events
  static void ProcessEvents(vtkObject* object,
                            unsigned long event,
                            void* clientdata,
                            void* calldata);
  
private:
  vtkKW3DMarkersWidget(const vtkKW3DMarkersWidget&);  //Not implemented
  void operator=(const vtkKW3DMarkersWidget&);  //Not implemented
};

#endif
