#ifndef ROO_PARAMHISTFUNC
#define ROO_PARAMHISTFUNC
#include <map>
#include "RooAbsReal.h"
#include "RooRealProxy.h"
#include "RooListProxy.h"
#include "RooObjCacheManager.h"
#include "RooDataHist.h"
class RooRealVar;
class RooArgList ;
class RooWorkspace;
class RooBinning;
class ParamHistFunc : public RooAbsReal {
public:
  ParamHistFunc() ;
  ParamHistFunc(const char *name, const char *title, const RooArgList& vars, const RooArgList& paramSet );
  ParamHistFunc(const char *name, const char *title, const RooArgList& vars, const RooArgList& paramSet, const TH1* hist );
  virtual ~ParamHistFunc() ;
  ParamHistFunc(const ParamHistFunc& other, const char* name = 0);
  virtual TObject* clone(const char* newname) const { return new ParamHistFunc(*this, newname); }
  const RooArgList& paramList() const { return _paramSet ; }
  Int_t numBins() const { return _dataSet.numEntries(); } 
  void setParamConst( Int_t, Bool_t=kTRUE );
  void setConstant(bool constant);
  void setShape(TH1* shape);
  RooRealVar& getParameter() const ;
  RooRealVar& getParameter( Int_t masterIdx ) const ;
  const RooArgSet* get(Int_t masterIdx) const { return _dataSet.get( masterIdx ) ; } 
  const RooArgSet* get(const RooArgSet& coord) const { return _dataSet.get( coord ) ; } 
  double binVolume() const { return _dataSet.binVolume(); }
  virtual Bool_t forceAnalyticalInt(const RooAbsArg&) const { return kTRUE ; }
  Int_t getAnalyticalIntegralWN(RooArgSet& allVars, RooArgSet& analVars, const RooArgSet* normSet,const char* rangeName=0) const ;
  Double_t analyticalIntegralWN(Int_t code, const RooArgSet* normSet, const char* rangeName=0) const ;
  static RooArgList createParamSet(RooWorkspace& w, const std::string&, const RooArgList& Vars);
  static RooArgList createParamSet(RooWorkspace& w, const std::string&, const RooArgList& Vars, Double_t, Double_t);
  static RooArgList createParamSet(const std::string&, Int_t, Double_t, Double_t);
  virtual std::list<Double_t>* binBoundaries(RooAbsRealLValue& , Double_t , Double_t ) const ;
  virtual std::list<Double_t>* plotSamplingHint(RooAbsRealLValue& obs, Double_t xlo, Double_t xhi) const ; 
  virtual Bool_t isBinnedDistribution(const RooArgSet& ) const {return kTRUE;}
protected:
  class CacheElem : public RooAbsCacheElement {
  public:
    CacheElem()  {} ;
    virtual ~CacheElem() {} ; 
    virtual RooArgList containedArgs(Action) { 
      RooArgList ret(_funcIntList) ; 
      ret.add(_lowIntList); 
      ret.add(_highIntList);
      return ret ; 
    }
    RooArgList _funcIntList ;
    RooArgList _lowIntList ;
    RooArgList _highIntList ;
    
  } ;
  mutable RooObjCacheManager _normIntMgr ; 
  
  
  RooListProxy _dataVars;       
  RooListProxy _paramSet ;            
  
  Int_t _numBins;
  mutable std::map<Int_t, Int_t> _binMap;
  mutable RooDataHist _dataSet;
   
  
  RooArgList   _ownedList ;       
  Int_t getCurrentBin() const ;
  Int_t addVarSet( const RooArgList& vars );
  Int_t addParamSet( const RooArgList& params );
  static Int_t GetNumBins( const RooArgSet& vars );
  Double_t evaluate() const;
  ClassDef(ParamHistFunc,5) 
};
#endif