//this file looks like plain C, but it's actually -*- c++ -*-
#ifndef __TQObservable__
#define __TQObservable__

#include "TNamed.h"
#include "TFolder.h"

class TQSample;
class TQFolder;
class TQTaggable;

#define DECLARE_OBSERVABLE_FACTORY(CLASSNAME,ARG) public:               \
  static const TQObservable::Factory<CLASSNAME> Factory;                \
  static const TQObservable::FactoryBase* getFactory()                  \
  { return &(CLASSNAME::Factory); }                                     \
  virtual bool hasFactory() const override { return true; }             \
  static TQObservable* tryCreateInstance(ARG);                          \
  virtual TQObservable* tryCreateInstanceVirtual(const TString& expr)  const final override \
  { return CLASSNAME::tryCreateInstance(expr); }

#define DEFINE_OBSERVABLE_FACTORY(CLASSNAME,ARG)                        \
  const TQObservable::Factory<CLASSNAME> CLASSNAME::Factory = TQObservable::Factory<CLASSNAME>(#CLASSNAME); \
  TQObservable* CLASSNAME::tryCreateInstance(ARG)

#define DEFINE_TEMPLATE_OBSERVABLE_FACTORY(CLASSNAME,TEMPLATE,ARG)      \
  template<class TEMPLATE> const TQObservable::Factory<CLASSNAME<TEMPLATE> > CLASSNAME<TEMPLATE>::Factory = TQObservable::Factory<CLASSNAME<TEMPLATE> >((std::string(#CLASSNAME) + "<" + TQObservableFactory::printType<TEMPLATE>() + ">").c_str()); \
  template<class TEMPLATE> TQObservable* CLASSNAME<TEMPLATE>::tryCreateInstance(ARG)

#define DEFINE_TEMPLATE_OBSERVABLE_FACTORY_SPECIALIZATION(CLASSNAME,TEMPLATE,ARG) \
  template<> TQObservable::Factory<CLASSNAME<TEMPLATE> > const CLASSNAME<TEMPLATE>::Factory = TQObservable::Factory<CLASSNAME<TEMPLATE> >(#CLASSNAME "<" #TEMPLATE ">"); \
  template<> TQObservable* CLASSNAME<TEMPLATE>::tryCreateInstance(ARG)    

#define DEFINE_TEMPLATE_ARGUMENT( type ) namespace TQObservableFactory { template<> constexpr const char* printType<type>() { return #type; } }

namespace TQObservableFactory {
  bool setupDefault();
  template <typename T> constexpr const char* printType() { return "undefined template argument, use DEFINE_TEMPLATE_ARGUMENT( ... ) to define!"; }
  // implement specializations for given types
}
  
class TQObservable : public TNamed {
  
private:
  static bool gIgnoreExpressionMismatch;
public:
  static TString makeObservableName(const TString& name);
  static bool matchExpressions(const TString& ex1, const TString& ex2, bool requirePrefix = false);
  static TString replaceBools(TString expression);
  static TString unreplaceBools(TString expression);
protected:
  TQSample * fSample = NULL; //!

  bool fIsManaged = false;
  bool fIsInitialized = false;

  class FactoryBase { // nested
  public:
    virtual const char* className() const = 0;
    virtual TQObservable* tryCreateInstance(const TString& expr) const = 0;
  };

  template<class ObsType> class Factory : public FactoryBase { // nested
  private:
    const std::string cName;
  public:
    Factory(const char* s) : cName(s) {};
    virtual const char* className() const final override { return this->cName.c_str(); }
    virtual TQObservable* tryCreateInstance(const TString& expr) const final override {
      return ObsType::tryCreateInstance(expr);
    }
  };

  static bool gAllowErrorMessages;

  virtual bool initializeSelf() = 0;
  virtual bool finalizeSelf() = 0;
  virtual bool hasFactory() const;
  
public:
  class Manager { // nested
    std::vector<const TQObservable::FactoryBase*> observableFactories;
    TFolder* activeSet = NULL;
    TFolder* sets = new TFolder("TQObservables","Global Observable List");
    Manager();
  public:
    TQObservable* createObservable(TString expression, TQTaggable* tags = NULL);
    void registerFactory(const TQObservable::FactoryBase* factory, bool putFirst);
    void printFactories();
    void clearFactories();
    bool setActiveSet(const TString& name);
    void cloneActiveSet(const TString& newName);
    void clearSet(const TString& name);
    void createEmptySet(const TString& name);
    TCollection* listOfSets();
		TFolder* getActiveSet();
    friend TQObservable;
  };
	static void clearAll();

	static Manager& getManager();

  bool isInitialized() const;
  virtual Long64_t getCurrentEntry() const = 0;

  static void allowErrorMessages(bool val);

  void setName(const TString& name);
  const TString& getNameConst() const;
  TString getName() const;

  static TString compileExpression(const TString& input, TQTaggable* tags, bool replaceBools=true);
  inline virtual bool isPrefixRequired() const {return false;}; //needs to be overridden if an observable (with a factory) should only be matched if it's prefix is present. In this case the observable must ensure to include its prefix in strings returned by getExpression, getActiveExpression,...
  
  TQObservable();
  TQObservable(const TString& expression);
  virtual ~TQObservable();

  static TQObservable* getObservable(const TString& exprname, TQTaggable* tags);
  static bool addObservable(TQObservable* obs);
  static bool addObservable(TQObservable* obs, const TString& name);

  static void printObservables(const TString& filter = "*");
  virtual void print() const;

  virtual bool initialize(TQSample * sample);
  virtual bool finalize();

  virtual bool isSetup() const;

  virtual double getValue() const = 0;
  virtual double getValueAt(int index) const;
  
  inline virtual int getNevaluations() const {return 1;}
  
  enum ObservableType {scalar,vector,unknown};
  inline virtual TQObservable::ObservableType getObservableType() const {return TQObservable::ObservableType::scalar;}

  virtual TQObservable* tryCreateInstanceVirtual (const TString& expr) const;

  virtual bool hasExpression() const;
  virtual const TString& getExpression() const;
  virtual void setExpression(const TString& expr);
  virtual TString getActiveExpression() const;
  virtual TString getCompiledExpression(TQTaggable* tags) const;
  virtual TObjArray* getBranchNames() const = 0;
 
  virtual TQObservable* getClone() const;

  static TQObservable::Manager manager;


  ClassDefOverride(TQObservable, 0); // abstract base class for data retrieval from trees

};

#endif
 TQObservable.h:1
 TQObservable.h:2
 TQObservable.h:3
 TQObservable.h:4
 TQObservable.h:5
 TQObservable.h:6
 TQObservable.h:7
 TQObservable.h:8
 TQObservable.h:9
 TQObservable.h:10
 TQObservable.h:11
 TQObservable.h:12
 TQObservable.h:13
 TQObservable.h:14
 TQObservable.h:15
 TQObservable.h:16
 TQObservable.h:17
 TQObservable.h:18
 TQObservable.h:19
 TQObservable.h:20
 TQObservable.h:21
 TQObservable.h:22
 TQObservable.h:23
 TQObservable.h:24
 TQObservable.h:25
 TQObservable.h:26
 TQObservable.h:27
 TQObservable.h:28
 TQObservable.h:29
 TQObservable.h:30
 TQObservable.h:31
 TQObservable.h:32
 TQObservable.h:33
 TQObservable.h:34
 TQObservable.h:35
 TQObservable.h:36
 TQObservable.h:37
 TQObservable.h:38
 TQObservable.h:39
 TQObservable.h:40
 TQObservable.h:41
 TQObservable.h:42
 TQObservable.h:43
 TQObservable.h:44
 TQObservable.h:45
 TQObservable.h:46
 TQObservable.h:47
 TQObservable.h:48
 TQObservable.h:49
 TQObservable.h:50
 TQObservable.h:51
 TQObservable.h:52
 TQObservable.h:53
 TQObservable.h:54
 TQObservable.h:55
 TQObservable.h:56
 TQObservable.h:57
 TQObservable.h:58
 TQObservable.h:59
 TQObservable.h:60
 TQObservable.h:61
 TQObservable.h:62
 TQObservable.h:63
 TQObservable.h:64
 TQObservable.h:65
 TQObservable.h:66
 TQObservable.h:67
 TQObservable.h:68
 TQObservable.h:69
 TQObservable.h:70
 TQObservable.h:71
 TQObservable.h:72
 TQObservable.h:73
 TQObservable.h:74
 TQObservable.h:75
 TQObservable.h:76
 TQObservable.h:77
 TQObservable.h:78
 TQObservable.h:79
 TQObservable.h:80
 TQObservable.h:81
 TQObservable.h:82
 TQObservable.h:83
 TQObservable.h:84
 TQObservable.h:85
 TQObservable.h:86
 TQObservable.h:87
 TQObservable.h:88
 TQObservable.h:89
 TQObservable.h:90
 TQObservable.h:91
 TQObservable.h:92
 TQObservable.h:93
 TQObservable.h:94
 TQObservable.h:95
 TQObservable.h:96
 TQObservable.h:97
 TQObservable.h:98
 TQObservable.h:99
 TQObservable.h:100
 TQObservable.h:101
 TQObservable.h:102
 TQObservable.h:103
 TQObservable.h:104
 TQObservable.h:105
 TQObservable.h:106
 TQObservable.h:107
 TQObservable.h:108
 TQObservable.h:109
 TQObservable.h:110
 TQObservable.h:111
 TQObservable.h:112
 TQObservable.h:113
 TQObservable.h:114
 TQObservable.h:115
 TQObservable.h:116
 TQObservable.h:117
 TQObservable.h:118
 TQObservable.h:119
 TQObservable.h:120
 TQObservable.h:121
 TQObservable.h:122
 TQObservable.h:123
 TQObservable.h:124
 TQObservable.h:125
 TQObservable.h:126
 TQObservable.h:127
 TQObservable.h:128
 TQObservable.h:129
 TQObservable.h:130
 TQObservable.h:131
 TQObservable.h:132
 TQObservable.h:133
 TQObservable.h:134
 TQObservable.h:135
 TQObservable.h:136
 TQObservable.h:137
 TQObservable.h:138
 TQObservable.h:139
 TQObservable.h:140
 TQObservable.h:141
 TQObservable.h:142
 TQObservable.h:143
 TQObservable.h:144
 TQObservable.h:145
 TQObservable.h:146
 TQObservable.h:147
 TQObservable.h:148
 TQObservable.h:149
 TQObservable.h:150
 TQObservable.h:151
 TQObservable.h:152
 TQObservable.h:153
 TQObservable.h:154
 TQObservable.h:155
 TQObservable.h:156