// @(#)root/treeviewer:$Id$
// Author: Bastien Dalla Piazza  02/08/2007

/*************************************************************************
 * Copyright (C) 1995-2007, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#ifndef ROOT_TParallelCoord
#define ROOT_TParallelCoord

#include "TAttLine.h"
#include "TNamed.h"

class TTree;
class TPaveText;
class TEntryList;
class TParallelCoordSelect;
class TParallelCoordVar;
class TParallelCoordRange;
class TList;
class TGaxis;
class TSelectorDraw;

class TParallelCoord : public TNamed {
public:
   enum EStatusBits {
      kVertDisplay     = BIT(14),      ///< If the axes are drawn vertically, false if horizontally.
      kCurveDisplay    = BIT(15),      ///< If the polylines are replaced by interpolated curves.
      kPaintEntries    = BIT(16),      ///< To paint all TParallelCoord entries.
      kLiveUpdate      = BIT(17),      ///< To paint the entries when being modified.
      kGlobalScale     = BIT(19),      ///< Every variable is on the same scale.
      kCandleChart     = BIT(20),      ///< To produce a candle chart.
      kGlobalLogScale  = BIT(21)       ///< Every variable in log scale.
   };

private:
   UInt_t          fNvar;                   ///< Number of variables.
   Long64_t        fCurrentFirst;           ///< First entry to display.
   Long64_t        fCurrentN;               ///< Number of entries to display.
   Long64_t        fNentries;               ///< Number of entries;
   Int_t           fDotsSpacing;            ///< Spacing between dots to draw the entries.
   Color_t         fLineColor;              ///< entries line color.
   Width_t         fLineWidth;              ///< entries line width.
   Int_t           fWeightCut;              ///< Specify a cut on the entries from their weight (see TParallelCoordVar::GetEvtWeight(Long64_t))
   TEntryList     *fCurrentEntries;         ///<-> Current selected entries in the tree.
   TEntryList     *fInitEntries;            ///<-> Selected entries when TParallelCoord first initialized.
   TTree          *fTree;                   ///<! Pointer to the TTree.
   TString         fTreeName;               ///< Name of the tree.
   TString         fTreeFileName;           ///< Name of the file containing the tree.
   TList          *fVarList;                ///< List of the variables.
   TList          *fSelectList;             ///< List of selections over the variables.
   TParallelCoordSelect* fCurrentSelection; ///<! Current Selection being edited.
   TGaxis         *fCandleAxis;             ///<! An axis used when displaying a candle chart.

   void            Init();
   void            PaintEntries(TParallelCoordSelect* sel=nullptr);
   void            SetAxesPosition();

public:
   TParallelCoord();
   TParallelCoord(Long64_t nentries);
   TParallelCoord(TTree* tree, Long64_t nentries);
   ~TParallelCoord() override;

   void           AddVariable(Double_t* val, const char* title="");
   void           AddVariable(const char* varexp);
   void           AddSelection(const char* title);
   void           ApplySelectionToTree(); // *MENU*
   static void    BuildParallelCoord(TSelectorDraw* selector, bool candle);
   void           CleanUpSelections(TParallelCoordRange* range);
   void           RemoveVariable(TParallelCoordVar* var);
   bool           RemoveVariable(const char* var);
   void           DeleteSelection(TParallelCoordSelect* sel);
   Int_t          DistancetoPrimitive(Int_t px, Int_t py) override;
   void           Draw(Option_t* options="") override;
   void           ExecuteEvent(Int_t entry, Int_t px, Int_t py) override;
   bool           GetCandleChart() {return TestBit(kCandleChart);}
   Long64_t       GetCurrentFirst() {return fCurrentFirst;}
   Long64_t       GetCurrentN() {return fCurrentN;}
   TParallelCoordSelect* GetCurrentSelection();
   bool           GetCurveDisplay() const {return TestBit(kCurveDisplay);}
   Int_t          GetDotsSpacing() const {return fDotsSpacing;}
   TEntryList    *GetEntryList(bool sel=true);
   Double_t       GetGlobalMin();
   Double_t       GetGlobalMax();
   bool           GetGlobalScale() {return TestBit(kGlobalScale);}
   bool           GetGlobalLogScale() {return TestBit(kGlobalLogScale);}
   Color_t        GetLineColor() {return fLineColor;}
   Width_t        GetLineWidth() {return fLineWidth;}
   Int_t          GetNbins();
   UInt_t         GetNvar() {return fNvar;}
   Long64_t       GetNentries() {return fNentries;}
   TList         *GetSelectList() {return fSelectList;}
   TParallelCoordSelect* GetSelection(const char* title);
   TTree         *GetTree();
   Double_t      *GetVariable(const char* var);
   Double_t      *GetVariable(Int_t i);
   TList         *GetVarList() {return fVarList;}
   bool           GetVertDisplay() const {return TestBit(kVertDisplay);}
   Int_t          GetWeightCut() const {return fWeightCut;};
   void           Paint(Option_t* options="") override;
   void           ResetTree();
   void           SaveEntryLists(const char* filename="", bool overwrite=false); // *MENU*
   void           SavePrimitive(std::ostream & out,Option_t *options) override;
   void           SaveTree(const char* filename="", bool overwrite=false); // *MENU*
   void           SetAxisHistogramBinning(Int_t n=100); // *MENU*
   void           SetAxisHistogramHeight(Double_t h=0.5); // *MENU*
   void           SetAxisHistogramLineWidth(Int_t lw=2); // *MENU*
   void           SetCandleChart(bool can); // *TOGGLE* *GETTER=GetCandleChart
   virtual void   SetCurveDisplay(bool curve=true) {SetBit(kCurveDisplay,curve);} // *TOGGLE* *GETTER=GetCurveDisplay
   void           SetCurrentEntries(TEntryList* entries) {fCurrentEntries = entries;}
   void           SetCurrentFirst(Long64_t);
   void           SetCurrentN(Long64_t);
   TParallelCoordSelect* SetCurrentSelection(const char* title);
   void           SetCurrentSelection(TParallelCoordSelect* sel);
   void           SetDotsSpacing(Int_t s=0); // *MENU*
   static void    SetEntryList(TParallelCoord* para, TEntryList* enlist);
   void           SetGlobalScale(bool gl); // *TOGGLE* *GETTER=GetGlobalScale
   void           SetGlobalLogScale(bool); // *TOGGLE* *GETTER=GetGlobalLogScale
   void           SetGlobalMin(Double_t min);
   void           SetGlobalMax(Double_t max);
   void           SetInitEntries(TEntryList* entries) {fInitEntries = entries;}
   void           SetLineColor(Color_t col) {fLineColor = col;}
   void           SetLineWidth(Width_t wid) {fLineWidth = wid;}
   void           SetLiveRangesUpdate(bool);
   void           SetNentries(Long64_t n) {fNentries = n;}
   void           SetTree(TTree* tree) {fTree = tree;}
   void           SetVertDisplay(bool vert=true); // *TOGGLE* *GETTER=GetVertDisplay
   void           SetWeightCut(Int_t w=0) {fWeightCut = w;} // *MENU*
   void           UnzoomAll(); // *MENU*

   ClassDefOverride(TParallelCoord,1); // To display parallel coordinates plots.
};

#endif
